aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-09 23:00:01 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-09 23:00:01 +0200
commit2367a8b63c3bcfe62d1aaf7d82c0ab3622f3b16c (patch)
tree3cef502c8bd0dfad3b6a119efef6b71bba8d1e5b
parent598be4cd1bdd79e4859ae30291f4d65682cc672a (diff)
downloadfwd-2367a8b63c3bcfe62d1aaf7d82c0ab3622f3b16c.tar.gz
fwd-2367a8b63c3bcfe62d1aaf7d82c0ab3622f3b16c.zip
initial ptr stuff
-rw-r--r--examples/ptrs.fwd22
-rw-r--r--examples/pure_move.fwd10
-rw-r--r--examples/references.fwd6
-rw-r--r--include/fwd/ast.h19
-rw-r--r--lib/fwdlib.hpp14
-rw-r--r--src/analyze.c26
-rw-r--r--src/lower.c1
-rw-r--r--src/move.c11
8 files changed, 102 insertions, 7 deletions
diff --git a/examples/ptrs.fwd b/examples/ptrs.fwd
new file mode 100644
index 0000000..a0f8aac
--- /dev/null
+++ b/examples/ptrs.fwd
@@ -0,0 +1,22 @@
+fwd_null(auto x, () null, (&auto) ok);
+fwd_copy(auto x, (auto, auto) ok);
+fwd_println(auto x);
+fwd_intalloc((*int) ok);
+
+main()
+{
+ fwd_intalloc() => *int i;
+ fwd_copy(i) => *int i1, *int i2;
+
+ /* convert raw pointer to reference, unsure if this should be a
+ * built-in or a library feature */
+ fwd_null(i1) => {
+ fwd_println("Pointer was null");
+ /* error out or something */
+ } => &int i;
+
+ fwd_println(i);
+
+ /* Try uncommenting, deref of raw pointer is not allowed! */
+ // i* + 20 => int something;
+}
diff --git a/examples/pure_move.fwd b/examples/pure_move.fwd
index a00666e..d32b9d5 100644
--- a/examples/pure_move.fwd
+++ b/examples/pure_move.fwd
@@ -1,14 +1,18 @@
requires_pure(&() p)
{
p();
+ /* ok since closure is pure */
+ p();
}
main()
{
20 => int twenty;
requires_pure() &=> {
- /* not allowed in pure context (though primitives should maybe
- * be excluded just to make people's lives easier?) */
- twenty + 10 => int thirty;
+ /* Try uncommenting!
+ * Not allowed in pure context (though primitives should maybe
+ * be excluded just to make people's lives easier?)
+ */
+ // twenty + 10 => int thirty;
}
}
diff --git a/examples/references.fwd b/examples/references.fwd
index 468f4a0..5b73aaf 100644
--- a/examples/references.fwd
+++ b/examples/references.fwd
@@ -16,7 +16,9 @@ main()
/* references are not active anymore so we can reference again */
references(twenty&, thirty&) => {
- /* not ok since twenty/thirty is actively borrowed */
- twenty + thirty => int fifty;
+ /* Try uncommenting!
+ * Not ok since twenty/thirty is actively borrowed
+ */
+ // twenty + thirty => int fifty;
};
}
diff --git a/include/fwd/ast.h b/include/fwd/ast.h
index 8eb39b7..726b5e3 100644
--- a/include/fwd/ast.h
+++ b/include/fwd/ast.h
@@ -255,8 +255,23 @@ static inline bool is_lvalue(struct ast *node)
/** @todo others */
return true;
- default:
- return false;
+ default: return false;
+ }
+
+ return false;
+}
+
+static inline bool is_trivially_copyable(struct type *type)
+{
+ switch (type->k) {
+ case TYPE_REF:
+ case TYPE_PTR:
+ case TYPE_FUNC_PTR:
+ case TYPE_PURE_CLOSURE:
+ /** @todo primitive types */
+ return true;
+
+ default: return false;
}
return false;
diff --git a/lib/fwdlib.hpp b/lib/fwdlib.hpp
index bb5084c..623dc13 100644
--- a/lib/fwdlib.hpp
+++ b/lib/fwdlib.hpp
@@ -40,6 +40,14 @@ static void fwd_copy(auto n, auto next)
return next(n, n);
}
+static void fwd_null(auto *x, auto fail, auto ok)
+{
+ if (x)
+ return ok(*x);
+ else
+ return fail();
+}
+
static void fwd_insert(auto container, auto elem, auto next)
{
container.insert(std::move(elem));
@@ -51,4 +59,10 @@ static void fwd_println(auto elem)
cout << elem << endl;
}
+static void fwd_intalloc(auto ok)
+{
+ int *p = new int{20};
+ ok(p);
+}
+
#endif /* FWDLIB_HPP */
diff --git a/src/analyze.c b/src/analyze.c
index dd85c08..8e76892 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -273,6 +273,31 @@ static int analyze_ref(struct state *state, struct scope *scope,
return 0;
}
+static int analyze_deref(struct state *state, struct scope *scope,
+ struct ast *node)
+{
+ struct ast *expr = deref_base(node);
+ if (analyze(state, scope, expr))
+ return -1;
+
+ if (expr->t->k == TYPE_PTR) {
+ semantic_error(node->scope, node,
+ "deref of raw ptr not allowed");
+ semantic_info(node->scope, node,
+ "use fwd_null() to convert to ref");
+ return -1;
+ }
+
+ if (expr->t->k != TYPE_REF) {
+ semantic_error(node->scope, node,
+ "deref of something not a reference");
+ return -1;
+ }
+
+ node->t = tptr_base(expr->t);
+ return 0;
+}
+
static int analyze_id(struct state *state, struct scope *scope,
struct ast *node)
{
@@ -443,6 +468,7 @@ static int analyze(struct state *state, struct scope *scope, struct ast *node)
case AST_PROC_DEF: ret = analyze_proc(state, scope, node); break;
case AST_VAR_DEF: ret = analyze_var(state, scope, node); break;
case AST_BLOCK: ret = analyze_block(state, scope, node); break;
+ case AST_DEREF: ret = analyze_deref(state, scope, node); break;
case AST_INIT: ret = analyze_init(state, scope, node); break;
case AST_CALL: ret = analyze_call(state, scope, node); break;
case AST_REF: ret = analyze_ref(state, scope, node); break;
diff --git a/src/lower.c b/src/lower.c
index 9f806f3..df095e4 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -248,6 +248,7 @@ static int lower_expr(struct state *state, struct ast *expr)
case AST_INIT: return lower_init(state, expr);
case AST_CLOSURE: return lower_closure(state, expr);
case AST_REF: return lower_expr(state, ref_base(expr));
+ case AST_DEREF: return lower_expr(state, deref_base(expr));
default:
internal_error("missing expr lowering");
return -1;
diff --git a/src/move.c b/src/move.c
index 9a89f75..7f54427 100644
--- a/src/move.c
+++ b/src/move.c
@@ -175,6 +175,13 @@ static int mvcheck_ref(struct state *state, struct ast *node)
return refcheck(state, ref_base(node));
}
+static int mvcheck_deref(struct state *state, struct ast *node)
+{
+ /** @todo good enough for now but probably won't hold when we start
+ * doing element lookups in structs etc. */
+ return mvcheck(state, deref_base(node));
+}
+
static int mvcheck_proc(struct state *state, struct ast *node)
{
/* extern, can't really do anything so just say it's fine */
@@ -271,6 +278,9 @@ static int mvcheck_id(struct state *state, struct ast *node)
if (def->k != AST_VAR_DEF)
return 0;
+ if (is_trivially_copyable(def->t))
+ return 0;
+
if (in_pure(state)) {
semantic_error(node->scope, node,
"move in pure context not allowed");
@@ -409,6 +419,7 @@ static int mvcheck(struct state *state, struct ast *node)
case AST_INIT: return mvcheck_init (state, node);
case AST_IF: return mvcheck_if (state, node);
case AST_REF: return mvcheck_ref (state, node);
+ case AST_DEREF: return mvcheck_deref (state, node);
case AST_EMPTY:
case AST_CONST_INT:
case AST_CONST_STR: