aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-03-30 22:36:53 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-03-30 22:41:21 +0300
commit957da9056c36a5eea15c6058701f7465b31f64a8 (patch)
tree7006d7c4ce258e88533e3b0347078a0264fe1bf3 /include
parentc87f5a8871edf6880b894a00b180c554ffd46d0a (diff)
downloadfwd-master.tar.gz
fwd-master.zip
WIP: rewrite C++ backend to be CHEADmaster
+ C allows for a bit more control, and we can manually handle closure contexts. For example `examples/fib.fwd` now works for effectively any `n`, pretty cool. + Fairly slow Fibonacci, I must admit. Initial profiling indicates it's mainly due to branch mispredictions, but I'll have to look into this a bit deeper. + The code is a bit hacked together, for now I'm more interested in getting things working, I'll worry about making things pretty later. + For testing, there's also initial support for modules, just so I can print stuff to the terminal + This commit is way too big, lol
Diffstat (limited to 'include')
-rw-r--r--include/fwd/ast.h40
-rw-r--r--include/fwd/compiler.h1
-rw-r--r--include/fwd/mod.h111
-rw-r--r--include/fwd/path.h38
-rw-r--r--include/fwd/scope.h5
5 files changed, 171 insertions, 24 deletions
diff --git a/include/fwd/ast.h b/include/fwd/ast.h
index 36aa8c8..69f7bf1 100644
--- a/include/fwd/ast.h
+++ b/include/fwd/ast.h
@@ -33,7 +33,9 @@ struct ast;
enum type_kind {
TYPE_ID = 1, TYPE_CONSTRUCT, TYPE_REF, TYPE_PTR, TYPE_CLOSURE,
- TYPE_PURE_CLOSURE, TYPE_FUNC_PTR, TYPE_VOID, TYPE_ERR
+ TYPE_PURE_CLOSURE, TYPE_FUNC_PTR, TYPE_VOID,
+ TYPE_I8, TYPE_I16, TYPE_I32, TYPE_I64,
+ TYPE_U8, TYPE_U16, TYPE_U32, TYPE_U64
};
struct type {
@@ -72,12 +74,6 @@ enum ast_kind {
AST_IF,
/** Nil check */
AST_NIL,
- /* Owning check */
- AST_OWN,
- /** Err branch */
- AST_ERR_BRANCH,
- /** Error throwing */
- AST_ERROR,
/** Call procedure. */
AST_CALL,
/** Procedure definition. */
@@ -152,6 +148,7 @@ enum ast_flag {
AST_FLAG_PREANALYZIS = (1 << 1),
AST_FLAG_NOMOVES = (1 << 2),
AST_FLAG_PUBLIC = (1 << 3),
+ AST_REQ_FRAME = (1 << 4),
};
struct ast {
@@ -286,9 +283,16 @@ static inline bool is_lvalue(struct ast *node)
static inline bool is_trivially_copyable(struct type *type)
{
switch (type->k) {
+ case TYPE_I8:
+ case TYPE_U8:
+ case TYPE_I16:
+ case TYPE_I32:
+ case TYPE_I64:
+ case TYPE_U16:
+ case TYPE_U32:
+ case TYPE_U64:
case TYPE_REF:
case TYPE_PTR:
- case TYPE_ERR:
case TYPE_FUNC_PTR:
case TYPE_PURE_CLOSURE:
/** @todo primitive types */
@@ -389,9 +393,8 @@ static inline bool is_trivially_copyable(struct type *type)
#define call_expr(x) return_a0(x, AST_CALL)
#define call_args(x) return_a1(x, AST_CALL)
-#define call_err(x) return_a2(x, AST_CALL)
-#define gen_call(expr, args, err, loc) \
- gen3(AST_CALL, expr, args, err, loc)
+#define gen_call(expr, args, loc) \
+ gen2(AST_CALL, expr, args, loc)
#define proc_id(x) return_s(x, AST_PROC_DEF)
#define proc_params(x) return_a0(x, AST_PROC_DEF)
@@ -410,20 +413,9 @@ static inline bool is_trivially_copyable(struct type *type)
#define gen_var(id, type, loc) \
gen_ast(AST_VAR_DEF, NULL, NULL, NULL, NULL, type, id, 0, 0., loc)
-#define err_branch_id(x) return_s(x, AST_ERR_BRANCH)
-#define err_branch_body(x) return_a0(x, AST_ERR_BRANCH)
-#define gen_err_branch(id, body, loc) \
- gen_ast(AST_ERR_BRANCH, body, NULL, NULL, NULL, NULL, id, 0, 0., loc)
-
-#define error_str(x) return_s(x, AST_ERROR)
-#define error_id(x) return_a0(x, AST_ERROR)
-#define gen_error(str, id, loc) \
- gen_ast(AST_ERROR, id, NULL, NULL, NULL, NULL, str, 0, 0., loc)
-
#define block_body(x) return_a0(x, AST_BLOCK)
-#define block_error(x) return_a1(x, AST_BLOCK)
-#define gen_block(body, err, loc) \
- gen2(AST_BLOCK, body, err, loc)
+#define gen_block(body, loc) \
+ gen1(AST_BLOCK, body, loc)
#define trait_id(x) return_s(x, AST_TRAIT_DEF)
#define trait_body(x) return_a1(x, AST_TRAIT_DEF)
diff --git a/include/fwd/compiler.h b/include/fwd/compiler.h
index b7f1569..ac4d7f5 100644
--- a/include/fwd/compiler.h
+++ b/include/fwd/compiler.h
@@ -21,5 +21,6 @@
* @return \c 0 if compilation was succesful, otherwise some non-zero value.
*/
int compile(const char *input);
+struct scope *compile_file(const char *file);
#endif /* FWD_COMPILER_H */
diff --git a/include/fwd/mod.h b/include/fwd/mod.h
new file mode 100644
index 0000000..6031c92
--- /dev/null
+++ b/include/fwd/mod.h
@@ -0,0 +1,111 @@
+#ifndef FWD_MOD_H
+#define FWD_MOD_H
+
+#include <stddef.h>
+#include <assert.h>
+#include <stdlib.h>
+
+typedef enum fwd_type {
+ FWD_VOID,
+ FWD_I8,
+ FWD_I16,
+ FWD_I32,
+ FWD_I64,
+ FWD_U8,
+ FWD_U16,
+ FWD_U32,
+ FWD_U64,
+ FWD_PTR,
+ /** @todo others */
+ FWD_END /* end of types, IDs above this are custom types I guess? */
+} fwd_type_t;
+
+typedef struct fwd_arg {
+ fwd_type_t t;
+ union {
+ int64_t i64;
+ void *p;
+ };
+} fwd_arg_t;
+
+/** @todo I hate this name */
+typedef struct fwd_extern_args {
+ size_t argc;
+ struct fwd_arg *args;
+} fwd_extern_args_t;
+
+typedef struct fwd_state fwd_state_t;
+typedef long (*fwd_extern_t)(fwd_extern_args_t args);
+typedef long (*fwd_open_t)(fwd_state_t *state);
+
+extern int fwd_register(struct fwd_state *state, const char *name, fwd_extern_t func, fwd_type_t rtype, ...);
+
+#define FWD_REGISTER(state, func, rtype, ...) \
+ fwd_register(state, #func, func, rtype __VA_OPT__(,) __VA_ARGS__, FWD_END)
+
+static inline void *fwd_arg(fwd_extern_args_t args, size_t idx, fwd_type_t id)
+{
+ assert(idx < args.argc);
+ assert(args.args[idx + 1].t == id);
+ switch (id) {
+ case FWD_I64: return &args.args[idx + 1].i64;
+ default:
+ }
+
+ return NULL;
+}
+
+#define FWD_ARG(args, idx, type, id) \
+ *(type *)fwd_arg(args, idx, id)
+
+#define FWD_ARG_T(args, idx, type) \
+ FWD_ARG(args, idx, type, FWD_T(type))
+
+static inline fwd_type_t fwd_t_signed(size_t s)
+{
+ switch (s) {
+ case 1: return FWD_I8;
+ case 2: return FWD_I16;
+ case 4: return FWD_I32;
+ case 8: return FWD_I64;
+ }
+
+ abort();
+ return FWD_END;
+}
+
+static inline fwd_type_t fwd_t_unsigned(size_t s)
+{
+ switch (s) {
+ case 1: return FWD_U8;
+ case 2: return FWD_U16;
+ case 4: return FWD_U32;
+ case 8: return FWD_U64;
+ }
+
+ abort();
+ return FWD_END;
+}
+
+static inline fwd_type_t fwd_t_ptr(size_t s)
+{
+ (void)s;
+ return FWD_PTR;
+}
+
+#define FWD_T(type) \
+ _Generic((type)(0),\
+ signed char : fwd_t_signed, \
+ signed short : fwd_t_signed, \
+ signed int : fwd_t_signed, \
+ signed long : fwd_t_signed, \
+ signed long long : fwd_t_signed, \
+ unsigned char : fwd_t_unsigned, \
+ unsigned short : fwd_t_unsigned, \
+ unsigned int : fwd_t_unsigned, \
+ unsigned long : fwd_t_unsigned, \
+ unsigned long long : fwd_t_signed, \
+ default: fwd_t_ptr)(sizeof(type))
+
+
+#endif /* FWD_MOD_H */
diff --git a/include/fwd/path.h b/include/fwd/path.h
new file mode 100644
index 0000000..277b33e
--- /dev/null
+++ b/include/fwd/path.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: copyleft-next-0.3.1 */
+/* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
+
+#ifndef FWD_PATH_H
+#define FWD_PATH_H
+
+/**
+ * @file path.h
+ *
+ * Path handling helpers.
+ */
+
+/**
+ * Get basename of file path.
+ * E.g. src/some/file.c -> file.c
+ *
+ * @param file File path to get basename from.
+ * @return Basename of \p file.
+ */
+char *fwd_basename(const char *file);
+
+/**
+ * Get directory name of path.
+ * E.g. src/some/file.c -> src/some
+ *
+ * @param file File path to get dirname from.
+ * @return Dirname of \p file.
+ */
+char *fwd_dirname(const char *file);
+
+/**
+ * Get current working directory.
+ *
+ * @return Current working directory.
+ */
+char *fwd_cwdname();
+
+#endif /* FWD_PATH */
diff --git a/include/fwd/scope.h b/include/fwd/scope.h
index ebe0261..ab268bc 100644
--- a/include/fwd/scope.h
+++ b/include/fwd/scope.h
@@ -24,6 +24,10 @@ enum scope_flags {
#define MAP_NAME visible
#include <conts/map.h>
+#define VEC_NAME mod_vec
+#define VEC_TYPE void *
+#include <conts/vec.h>
+
/**
* Scope.
* Responsible for keeping track of visibilities and
@@ -54,6 +58,7 @@ struct scope {
struct visible symbols;
struct visible traits;
struct visible types;
+ struct mod_vec mods;
enum scope_flags flags;
};