+++ /dev/null
-The current way I do symbol resolution is:
- - Join all top level symbols at parse time into a single struct
- - Add all top level symbols to a string table that maps from
- their name to their AST node
- - Then step through every function linearly and resolve each symbol using the table
- * Function locals are added when they are declared and then removed at the end
- of their scope as would be expected
-
-This method works, but it is not great and feels like a hack.
- - References to other things are just pointers to the AST node
- - This produces a heavy reliance on the AST instead of other, more efficient data structures
-
-
-
-
-PROPOSED NEW METHOD:
- Every top level declaration will add a declinfo entry that will contain the following information:
- - Identifier
- - Pointer to AST node
+++ /dev/null
-Note: ~ is empty
-Goal: Design the language to have no ambiguity (so a greedy algorithm can work)
-
-
-SOURCE_FILE = TOP_LEVEL_STATEMENT ; SOURCE_FILE | ~
-
-TOP_LEVEL_STATEMENT
- = COMMENT -- Should comments not be passed to the parser? Depends if I need to look at them. Probably not
- | USE_DECLARATION
- | EXPORT_DECLARATION
- | FOREIGN_DECLARATION
- | TOP_LEVEL_DECLARATION
-
-COMMENT = TOKEN_TYPE_COMMENT
-
-USE_DECLARATION = use TOKEN_TYPE_LITERAL_STRING
-
-EXPORT_DECLARATION = export TOP_LEVEL_DECLARATION
-
-FOREIGN_DECLARATION = foreign TOKEN_TYPE_LITERAL_STRING TOKEN_TYPE_LITERAL_STRING :: TOP_LEVEL_VALUE
-
-TOP_LEVEL_DECLARATION = TOKEN_TYPE_SYMBOL :: TOP_LEVEL_VALUE
-
-TOP_LEVEL_VALUE
- = FUNCTION_DECLARATION
- | STRUCT_DECLARATION
-
-FUNCTION_DECLARATION = proc FUNCTION_TYPE BLOCK
-
-FUNCTION_TYPE = ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL
-
--- This may be too weird...
-BLOCK = { STATEMENTS | ---
-STATEMENTS = STATEMENT ; STATEMENTS | }
-
-STATEMENT
- = ASSIGNMENT_STATEMENT
- | IF_STATEMENT
- | FOR_STATEMENT
- | RETURN_STATEMENT
- | EXPRESSION
-
-ASSIGNMENT_STATEMENT = TOKEN_TYPE_SYMBOL = EXPRESSION
-
-IF_STATEMENT
- = if EXPRESSION BLOCK ELSE_IF_STATEMENT ELSE_STATEMENT
-
-ELSEIF_STATEMENT = elseif EXPRESSION BLOCK ELSEIF_STATEMENT | ~
-
-ELSE_STATEMENT = else BLOCK | ~
-
--- This needs to be better
-FOR_STATEMENT = for STATEMENT ; EXPRESSION ; STATEMENT BLOCK
-
-RETURN_STATEMENT = return EXPRESSION
-
--- Remove abiguity in implementation
-EXPRESSION
- = EXPRESSION + EXPRESSION
- | EXPRESSION - EXPRESSION
- | EXPRESSION * EXPRESSION
- | EXPRESSION / EXPRESSION
- | EXPRESSION % EXPRESSION
- | do BLOCK
- | FUNCTION_CALL -- This could have some abiguity with just the symbol
- | ( EXPRESSION )
- | TOKEN_TYPE_SYMBOL
-
-FUNCTION_CALL = TOKEN_TYPE_SYMBOL ( EXPRESSION_LIST )
-
--- Implement just using a loop
-COMMA_LIST(T) = T | T , COMMA_LIST(T)
-
-FUNCTION_PARAMS = COMMA_LIST(TOKEN_TYPE_SYMBOL :: TOKEN_TYPE_SYMBOL)
-EXPRESSION_LIST = COMMA_LIST(EXPRESSION)
-
-STRUCT_DECLARATION = struct { STRUCT_MEMBERS }
-STRUCT_MEMBERS = COMMA_LIST(TOKEN_TYPE_SYMBOL :: TOKEN_TYPE_SYMBOL)
typedef struct AstSizeOf AstSizeOf;
typedef struct AstReturn AstReturn;
+typedef struct AstBreak AstBreak;
+typedef struct AstContinue AstContinue;
typedef struct AstBlock AstBlock;
typedef struct AstIf AstIf;
struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; };
// Intruction Node
-struct AstReturn { AstNode_base; AstTyped* expr; };
+struct AstReturn { AstNode_base; AstTyped* expr; };
+struct AstBreak { AstNode_base; u64 count; };
+struct AstContinue { AstNode_base; u64 count; };
// Structure Nodes
-struct AstBlock { AstNode_base; AstNode *body; Scope *scope; };
-struct AstWhile { AstNode_base; AstTyped *cond; AstNode *stmt; };
+struct AstBlock { AstNode_base; AstNode *body; Scope *scope; };
+struct AstWhile { AstNode_base; AstTyped *cond; AstNode *stmt; };
struct AstFor {
AstNode_base;
+++ /dev/null
-
-print :: foreign "host" "print" proc (val: i32) ---
-
-export main :: proc {
-
- while true {
- print(8000);
- break;
- }
-
- x := 0;
- while x < 10 {
-
- if x == 4 {
-
- x := 1;
- while x < 1000000 {
- print(x);
-
- if x > 4 { break; }
-
- x = x + 1;
- }
-
- }
-
- if x == 2 {
-
- x := 1;
- while x <= 5 {
- if x == 3 {
- x = x + 1;
- continue;
- }
-
- print(x);
- x = x + 1;
- }
-
- }
-
- x = x + 1;
- }
-
-}
+++ /dev/null
-
-print :: foreign "host" "print" proc (value: i32) ---
-print_float :: foreign "host" "print" proc (value: f32) ---
-print_if :: foreign "host" "print" proc (i: i32, f: f32) ---
-
-export main :: proc {
- output := do_stuff() - 1;
-
- if output == -66 {
- new_output := abs(output) * 2;
- print(new_output);
-
- } elseif output == -67 {
- print(factorial(6));
-
- } else {
- print(-1);
- }
-
- print(fib(5));
-
- print(output);
- print_float(float_test());
-
- print_if(output, float_test());
-}
-
-factorial :: proc (n: i32) -> i32 {
- if n <= 1 { return 1; }
-
- return n * factorial(n - 1);
-}
-
-foo :: proc -> i32 {
- return 10;
-}
-
-add :: proc (a: i32, b: i32) -> i32 {
- return a + b;
-}
-
-// NOTE: There is a weird bug here if the else is used instead
-// This is because the WASM embedder does not think that it
-// is possible that all code paths are covered with returning
-// an i32. This will need to be fixed.
-abs :: proc (val: i32) -> i32 {
- if val <= 0 { return -val; }
- // else { return val; };
- return val;
-}
-
-fib :: proc (n: i32) -> i32 {
- if n <= 1 { return 1; }
- return fib(n - 1) + fib(n - 2);
-}
-
-diff_square :: proc (a: i32, b: i32) -> i32 {
- // Typechecked
- c := a - b; // Mutable
- d :: a + b; // Constant
-
- {
- c := a * 2;
- d := (b + a) * 2;
- }
-
- return c * d;
-}
-
-do_stuff :: proc -> i32 {
- res := diff_square(4 + 5, 2 + 3);
- res = res + foo();
- return res * -1;
-}
-
-float_test :: proc -> f32 {
- return 3.14159f;
-}
+++ /dev/null
-print :: foreign "host" "print" proc (value: i32) ---
-
-simple_test :: proc {
- a: i32 = 5;
- b: i32 = 6;
-
- if a > b {
- foo := 123;
- print(foo);
- }
-
- c :: a + foo();
- print(c);
-}
-
-fib :: proc (n: i32) -> i32 {
- if n <= 1 { return 1; }
-
- return fib(n - 1) + fib(n - 2);
-}
-
-foo :: proc -> i32 {
- return 10;
-}
-
-print_nums :: proc (a: i32, b: i32, c: i32) {
- print(a);
- print(b);
- print(c);
-}
soa.positions[5].x = 1;
soa.positions[5].y = 2;
soa.positions[2].x = 1001;
- vec2_set(^(soa.positions[6]));
+ (^(soa.positions[6])).vec2_set();
vec2_set(soa.things[2]);
print((^(soa.positions[6])).v2magnitude());
+++ /dev/null
-use "progs/print_funcs"
-use "progs/other"
-use "progs/intrinsics"
-
-something_else :: proc (n: i32) -> i32 {
- return 100 * n + global_value;
-}
-
-in_unit_circle :: proc #export (x: f32, y: f32) -> bool {
- return (x * x) + (y * y) < 1.0f;
-}
-
-echo :: proc (n: i32) -> i32 {
- print_i32(n);
- return n;
-}
-
-global_value :: echo(fib(4) * 2);
-
-test_proc :: local_brute;
-
-local_brute :: proc {
- a := 123;
- b := 123.0f;
- c := 123.0;
-
- {
- d := 5.0f;
- e := 12.3;
-
- print_f32(d);
- print_f64(e);
- }
-
- print_i32(a);
- print_f32(b);
- print_f64(c);
-}
-
-// This is the entry point
-main2 :: proc #export {
- i := 0;
- while i < 10 {
- res :: clz_i32(fib(i));
- print_i32(res);
- i += 1;
- }
-
- i = 0;
- while i < 10 {
- res :: factorial(i);
- print_i32(res);
- i += 1;
- }
-
- x : i32;
- y := 0;
- while y < 5 {
-
- x = 0;
- while x < 5 {
- if x == 3 {
- x += 1;
- continue;
- }
-
- print_i32((x + y * 5) % 10);
- x += 1;
- }
-
- if y > 2 { break; }
-
- y += 1;
- }
-}
-
-// Foo :: struct {
-// bar : Bar;
-// something : i32;
-// other : i64;
-// }
-//
-// Bar :: struct {
-// x : f32;
-// y : f32;
-// z : f32;
-// }
-
-main :: proc #export {
- test_proc();
- local_brute();
-
- print_i32(clz_i32(16));
- print_f32(sqrt_f32(2.0f));
-
- print_i32(5 * 6 + 2 * 3);
- print_bool(in_unit_circle(0.5f, 0.5f));
-
- big_num := fib(factorial(4));
-
- something :: other_value(0);
- something_else :: other_value(1);
-
- condition := big_num < something;
-
- if condition {
- print_i32(big_num);
- print_i32(something);
- print_i32(something_else);
- }
-}
-
retval = (AstNode *) parse_for_stmt(parser);
break;
- case Token_Type_Keyword_Break:
- retval = make_node(AstNode, Ast_Kind_Break);
- retval->token = expect_token(parser, Token_Type_Keyword_Break);
+ case Token_Type_Keyword_Break: {
+ AstBreak* bnode = make_node(AstBreak, Ast_Kind_Break);
+ bnode->token = expect_token(parser, Token_Type_Keyword_Break);
+
+ u64 count = 1;
+ while (parser->curr->type == Token_Type_Keyword_Break) {
+ consume_token(parser);
+ count++;
+ }
+ bnode->count = count;
+
+ retval = (AstNode *) bnode;
break;
+ }
- case Token_Type_Keyword_Continue:
- retval = make_node(AstNode, Ast_Kind_Break);
- retval->token = expect_token(parser, Token_Type_Keyword_Continue);
+ case Token_Type_Keyword_Continue: {
+ AstContinue* cnode = make_node(AstBreak, Ast_Kind_Continue);
+ cnode->token = expect_token(parser, Token_Type_Keyword_Continue);
+
+ u64 count = 1;
+ while (parser->curr->type == Token_Type_Keyword_Continue) {
+ consume_token(parser);
+ count++;
+ }
+ cnode->count = count;
+
+ retval = (AstNode *) cnode;
break;
+ }
default:
break;
*pcode = code;
}
-COMPILE_FUNC(structured_jump, b32 jump_backward) {
+COMPILE_FUNC(structured_jump, i32 jump_count) {
bh_arr(WasmInstruction) code = *pcode;
i32 labelidx = 0;
- u8 wanted = jump_backward ? 2 : 1;
+ u8 wanted = (jump_count < 0) ? 2 : 1;
b32 success = 0;
+ if (jump_count < 0) jump_count = -jump_count;
+
i32 len = bh_arr_length(mod->structured_jump_target) - 1;
for (u8* t = &bh_arr_last(mod->structured_jump_target); len >= 0; len--, t--) {
- if (*t == wanted) {
+ if (*t == wanted) jump_count--;
+ if (jump_count == 0) {
success = 1;
break;
}
case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break;
case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break;
case Ast_Kind_For: compile_for(mod, &code, (AstFor *) stmt); break;
- case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break;
- case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break;
+ case Ast_Kind_Break: compile_structured_jump(mod, &code, ((AstBreak *) stmt)->count); break;
+ case Ast_Kind_Continue: compile_structured_jump(mod, &code, -((AstContinue *) stmt)->count); break;
case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break;
default: compile_expression(mod, &code, (AstTyped *) stmt); break;
}