Starting on the semantic pass phase
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 25 May 2020 21:47:38 +0000 (16:47 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 25 May 2020 21:47:38 +0000 (16:47 -0500)
docs/plan
docs/thoughts [new file with mode: 0644]
onyx
onyxparser.c
onyxutils.c
progs/minimal.onyx

index 666e18db47478aa696944b1932e39a9e001e80b3..0d11788da66a2f1e20653d262f3b92173f05d1c6 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -9,15 +9,20 @@ WHAT:
 WHY:
        ONYX was made to help me learn about compiler design.
 
+END GOAL:
+       ONYX will be used to make a simple-ish game for the browser that leverages
+       WASM and WebGL for a performant experience. Language design will reflect the
+       needs of the game programming.
+
 FEATURES:
        - Strong type system
-       - Smart package loading
-       - Structs and enums
        - functions (no anonymous functions)
+       - Structs and enums
        - Control structures
                if, for, switch
        - pointers
        - inferred typing
+       - Smart package loading
        - defer
        ? polymorphic functions
 
@@ -28,13 +33,13 @@ EXAMPLE CODE:
 
 use "core"; // Looks for "core.onyx" in the current directory
 
-Foo :: struct { x: i32, y: i32 };
+Foo :: struct { x i32, y i32 };
 
-export add :: (a: i32, b: i32) -> i32 {
-       return a + b;   
+export add :: proc (a i32, b i32) -> i32 {
+       return a + b;
 };
 
-foo :: (a: i32) -> Foo {
+foo :: proc (a i32) -> Foo {
        return Foo { x = a, y = 0 };
 }
 
@@ -42,16 +47,15 @@ MVP CODE:
 
 /* Comments need to be parsed */
 
-export proc add :: (a i32, b i32) -> i32 {
+export add :: proc (a i32, b i32) -> i32 {
        return a + b;
 }
 
-export proc max :: (a i32, b i32) -> i32 {
+export max :: proc (a i32, b i32) -> i32 {
        /* Curly braces are required */
-
        if a > b {
                return a;
        } else {
                return b;
        }
-}
\ No newline at end of file
+}
diff --git a/docs/thoughts b/docs/thoughts
new file mode 100644 (file)
index 0000000..ddf255f
--- /dev/null
@@ -0,0 +1,24 @@
+Type checking at parse time:\r
+       Why couldn't this work?\r
+       * Every variable is of known type or the type must be known by immediate assignment\r
+       * This requires that functions are declared in a particular order like C\r
+       * This also requires immediate evaluation of external symbols (C #include style)\r
+               - Don't like this at all\r
+               - Want a proper module system\r
+\r
+       /* foo.onyx */\r
+       foo :: proc (a i32) -> f32 {\r
+               return a as f32;\r
+       }\r
+\r
+\r
+       /* main.onyx */\r
+       use "foo";\r
+\r
+       export main :: proc () -> void {\r
+               a := 2.0f + foo(5);\r
+       }\r
+\r
+       foo(5) would have a left node of SYMBOL:foo\r
+       This will be resolved in a later stage between the parsing and semantic pass\r
+       \r
diff --git a/onyx b/onyx
index 6ec79ea91f5dad35682e1545c61ee8a15a197f14..9015a7d81bda3362b478f258095335967a094e0e 100755 (executable)
Binary files a/onyx and b/onyx differ
index 82949e7966126cd802b8d017904ec2ab42b530b3..493527c51d63a5b087022e68e042ea73b6e9ea63 100644 (file)
@@ -207,6 +207,13 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
        case TOKEN_TYPE_SYMBOL: {
                OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
                OnyxAstNode* sym_node = lookup_identifier(parser, sym_token);
+               if (sym_node == NULL) {
+                       onyx_token_null_toggle(*sym_token);
+                       onyx_message_add(parser->msgs,
+                               ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL,
+                               sym_token->pos, sym_token->token);
+                       onyx_token_null_toggle(*sym_token);
+               }
 
                // TODO: Handle calling a function
                return sym_node;
index 02d191f59189e4ed556416fedabfd66542e99cf4..5fdddcde8d9678b0fedfa4956fc927240456193d 100644 (file)
@@ -2,26 +2,4 @@
 
 void onyx_ast_print(OnyxAstNode* node) {
        if (node == NULL) return;
-
-       bh_printf("%s <%d> ", onyx_ast_node_kind_string(node->kind), node->flags);
-       if (node->token)
-               bh_printf("[%b] ", node->token->token, (int) node->token->length);
-
-       if ((i64) node->left > 10) { // HACK: but okay
-               bh_printf("(");
-               onyx_ast_print(node->left);
-               bh_printf(") ");
-       }
-       if ((i64) node->right > 10) { // HACK: but okay
-               bh_printf("(");
-               onyx_ast_print(node->right);
-               bh_printf(")");
-       }
-
-       if (node->next) {
-               bh_printf("{");
-               onyx_ast_print(node->next);
-               bh_printf("}");
-       }
-
 }
index 5b82b6991324ecb41b61789d3049a58415995b5b..ee2e65161e1093c15337564d2d5b391e96b6ca5b 100644 (file)
@@ -8,13 +8,13 @@ export add :: proc (a i32, b i32) -> i32 {
        return a + b;
 }
 
-c :: proc () -> void ---
-
 export mul :: proc (a i32, b i32) -> i32 {
+       /* Typechecked */
        c: const i32 = a - b;
 
        /*  Don't love this syntax, but it's easy to parse so whatever
                Inferred type, but constant */
+       /* a and b are both i32, so i32 + i32 is i32 so d is i32 */
        d: const = a + b;
 
        return c * d;