From: Michael D. Lowis Date: Wed, 30 May 2018 16:24:58 +0000 (-0400) Subject: added support for constant and variable bindings at the top level X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=7f58520abeeae543d66ac2d5915a2fe809d6c490;p=proto%2Fsclpl.git added support for constant and variable bindings at the top level --- diff --git a/source/ast.c b/source/ast.c index 7891139..76d0104 100644 --- a/source/ast.c +++ b/source/ast.c @@ -3,7 +3,7 @@ static AST* ast(ASTType type) { AST* tree = emalloc(sizeof(AST)); memset(tree, 0, sizeof(AST)); - tree->type = type; + tree->nodetype = type; return tree; } @@ -14,7 +14,7 @@ AST* String(Tok* val) { } char* string_value(AST* val) { - assert(val->type == AST_STRING); + assert(val->nodetype == AST_STRING); return val->value.text; } @@ -25,7 +25,7 @@ AST* Symbol(Tok* val) { } char* symbol_value(AST* val) { - assert(val->type == AST_SYMBOL); + assert(val->nodetype == AST_SYMBOL); return val->value.text; } @@ -36,7 +36,7 @@ AST* Char(Tok* val) { } uint32_t char_value(AST* val) { - assert(val->type == AST_CHAR); + assert(val->nodetype == AST_CHAR); return val->value.character; } @@ -47,7 +47,7 @@ AST* Integer(Tok* val) { } intptr_t integer_value(AST* val) { - assert(val->type == AST_INT); + assert(val->nodetype == AST_INT); return val->value.integer; } @@ -58,7 +58,7 @@ AST* Float(Tok* val) { } double float_value(AST* val) { - assert(val->type == AST_FLOAT); + assert(val->nodetype == AST_FLOAT); return val->value.floating; } @@ -69,7 +69,7 @@ AST* Bool(Tok* val) { } bool bool_value(AST* val) { - assert(val->type == AST_BOOL); + assert(val->nodetype == AST_BOOL); return val->value.boolean; } @@ -80,23 +80,29 @@ AST* Ident(Tok* val) { } char* ident_value(AST* val) { - assert(val->type == AST_IDENT); + assert(val->nodetype == AST_IDENT); return val->value.text; } -AST* Let(Tok* name, AST* value) { - AST* node = ast(AST_LET); - node->value.let.name = name->value.text; - node->value.let.value = value; +AST* Var(Tok* name, AST* value, bool constant) { + AST* node = ast(AST_VAR); + node->value.var.name = name->value.text; + node->value.var.value = value; + node->value.var.constant = constant; return node; } -char* let_name(AST* let) { - assert(let->type == AST_LET); - return let->value.let.name; +char* var_name(AST* var) { + assert(var->nodetype == AST_VAR); + return var->value.var.name; } -AST* let_value(AST* let) { - assert(let->type == AST_LET); - return let->value.let.value; +AST* var_value(AST* var) { + assert(var->nodetype == AST_VAR); + return var->value.var.value; +} + +bool var_const(AST* var) { + assert(var->nodetype == AST_VAR); + return var->value.var.constant; } diff --git a/source/lexer.l b/source/lexer.l index 9105367..a34922f 100644 --- a/source/lexer.l +++ b/source/lexer.l @@ -30,9 +30,12 @@ NOSPACE [^ \t\r\n] %% -<> { return T_END_FILE; } +[ \t\r\n] { /* whitespace is insignificant */ } +<> { return T_END_FILE; } "let" { return T_LET; } +"var" { return T_VAR; } + "if" { return T_IF; } "then" { return T_THEN; } "else" { return T_ELSE; } diff --git a/source/parser.c b/source/parser.c index 8e47f1c..3d3f04d 100644 --- a/source/parser.c +++ b/source/parser.c @@ -1,6 +1,6 @@ #include -static AST* const_definition(Parser* p); +static AST* const_definition(Parser* p, bool constant); static AST* const_expression(Parser* p); static AST* definition(Parser* p); static AST* expression(Parser* p); @@ -62,26 +62,22 @@ static Tok* expect_val(Parser* parser, TokType type) { AST* toplevel(Parser* p) { AST* ret = NULL; if (!match(p, T_END_FILE)) { - if (accept(p, T_LET)) - ret = const_definition(p); + TokType type = peek(p)->type; + if (accept(p, T_LET) || accept(p, T_VAR)) + ret = const_definition(p, (type == T_LET)); else error(p, "only definitions are allowed at the toplevel"); } return ret; } -static AST* const_definition(Parser* p) { +static AST* const_definition(Parser* p, bool constant) { AST* expr; Tok* id = expect_val(p, T_ID); -// if (peek(p)->type == T_LPAR) { -// expr = function(p); -// } else { - type_annotation(p); - expect(p, T_ASSIGN); - expr = const_expression(p); - expect(p, T_END); -// } - return Let(id, expr); + type_annotation(p); + expect(p, T_ASSIGN); + expr = const_expression(p); + return Var(id, expr, constant); } static AST* const_expression(Parser* p) { diff --git a/source/pprint.c b/source/pprint.c index 0140b4a..f47fe8b 100644 --- a/source/pprint.c +++ b/source/pprint.c @@ -95,8 +95,8 @@ static const char* tree_type_to_string(ASTType type) { static void pprint_literal(FILE* file, AST* tree, int depth) { - printf("%s:", tree_type_to_string(tree->type)); - switch(tree->type) { + printf("%s:", tree_type_to_string(tree->nodetype)); + switch(tree->nodetype) { case AST_STRING: printf("\"%s\"", string_value(tree)); break; case AST_SYMBOL: printf("%s", symbol_value(tree)); break; case AST_IDENT: printf("%s", ident_value(tree)); break; @@ -116,11 +116,13 @@ void pprint_tree(FILE* file, AST* tree, int depth) return; } print_indent(file, depth); - switch (tree->type) { - case AST_LET: - printf("(let %s ", let_name(tree)); - pprint_tree(file, let_value(tree), depth); - printf(")"); + switch (tree->nodetype) { + case AST_VAR: + printf("(%s %s ", + (var_const(tree) ? "let" : "var"), + var_name(tree)); + pprint_tree(file, var_value(tree), depth); + printf(")\n"); break; default: diff --git a/source/sclpl.h b/source/sclpl.h index d6393e6..21784bf 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -40,9 +40,10 @@ void vec_set(vec_t* vec, size_t index, void* data); /* Token Types *****************************************************************************/ typedef enum { - T_NONE, T_ERROR, T_END_FILE, T_ID, T_CHAR, T_INT, T_FLOAT, T_BOOL, T_STRING, + T_NONE, T_ERROR, T_END_FILE, T_LET, T_VAR, + T_ID, T_CHAR, T_INT, T_FLOAT, T_BOOL, T_STRING, T_LBRACE, T_RBRACE, T_LBRACK, T_RBRACK, T_LPAR, T_RPAR, T_COMMA, T_SQUOTE, - T_DQUOTE, T_END, T_COLON, T_AMP, T_LET, T_IF, T_THEN, T_ELSE, T_ASSIGN + T_DQUOTE, T_END, T_COLON, T_AMP, T_IF, T_THEN, T_ELSE, T_ASSIGN } TokType; typedef struct { @@ -86,18 +87,19 @@ Type* PtrTo(Type* type); /* AST Types *****************************************************************************/ typedef enum { - AST_LET, AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT + AST_VAR, AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT } ASTType; typedef struct AST { - ASTType type; + ASTType nodetype; + Type* datatype; union { /* Definition Node */ struct { char* name; - struct AST* type; struct AST* value; - } let; + bool constant; + } var; /* String, Symbol, Identifier */ char* text; /* Character */ @@ -140,9 +142,10 @@ AST* Ident(Tok* val); char* ident_value(AST* val); /* Definition */ -AST* Let(Tok* name, AST* value); -char* let_name(AST* let); -AST* let_value(AST* let); +AST* Var(Tok* name, AST* value, bool constant); +char* var_name(AST* var); +AST* var_value(AST* var); +bool var_const(AST* var); /* Pretty Printing *****************************************************************************/