source/codegen.o
.PHONY: all specs tests
-all: sclpl specs tests
+all: sclpl tests
lib${BIN}.a: ${OBJS}
${AR} ${ARFLAGS} $@ $^
tests: $(BIN)
@echo "Parsing example file..."
- ./sclpl -Aast < example.src
+ ./sclpl -Aast example.src
.c.o:
${CC} ${CFLAGS} -c -o $@ $<
provide (main)
let const_true bool = true
-let const_false bool = false
-let const_uint int = 123
-let const_string string = ""
+#let const_false bool = false
+#let const_uint int = 123
+#let const_string string = ""
var var_true bool = true
var var_false bool = false
assert(var->nodetype == AST_VAR);
return (var->value.var.flags == SF_CONSTANT);
}
+
+AST* Func(AST* args, AST* body)
+{
+ AST* node = ast(AST_FUNC);
+ node->value.func.args = args;
+ node->value.func.body = body;
+ return node;
+}
+
+AST* func_args(AST* func) {
+ assert(func->nodetype == AST_FUNC);
+ return func->value.func.args;
+}
+
+AST* func_body(AST* func) {
+ assert(func->nodetype == AST_FUNC);
+ return func->value.func.body;
+}
+
+AST* ExpList(void) {
+ AST* node = ast(AST_EXPLIST);
+ node->value.explist.nexprs = 0;
+ node->value.explist.exprs = 0;
+ return node;
+}
+
+AST** explist_get(AST* explist, size_t* nexprs) {
+ assert(explist->nodetype == AST_EXPLIST);
+ *nexprs = explist->value.explist.nexprs;
+ return explist->value.explist.exprs;
+}
+
+void explist_append(AST* explist, AST* expr) {
+ assert(explist->nodetype == AST_EXPLIST);
+ explist->value.explist.nexprs += 1;
+ explist->value.explist.exprs = realloc(explist->value.explist.exprs, explist->value.explist.nexprs * sizeof(AST*));
+ explist->value.explist.exprs[explist->value.explist.nexprs-1] = expr;
+}
+
+void explist_prepend(AST* explist, AST* expr) {
+ assert(explist->nodetype == AST_EXPLIST);
+ explist->value.explist.nexprs++;
+ explist->value.explist.exprs = realloc(explist->value.explist.exprs, explist->value.explist.nexprs * sizeof(AST*));
+ memmove(explist->value.explist.exprs+1, explist->value.explist.exprs, explist->value.explist.nexprs-1);
+ explist->value.explist.exprs[0] = expr;
+}
+
+AST* If(AST* cond, AST* b1, AST* b2) {
+ AST* node = ast(AST_IF);
+ node->value.ifexp.cond = cond;
+ node->value.ifexp.b1 = b1;
+ node->value.ifexp.b2 = b2;
+ return node;
+}
+
+AST* if_cond(AST* ifexp) {
+ assert(ifexp->nodetype == AST_IF);
+ return ifexp->value.ifexp.cond;
+}
+
+AST* if_then(AST* ifexp) {
+ assert(ifexp->nodetype == AST_IF);
+ return ifexp->value.ifexp.b1;
+}
+
+AST* if_else(AST* ifexp) {
+ assert(ifexp->nodetype == AST_IF);
+ return ifexp->value.ifexp.b2;
+}
+
+AST* Apply(AST* func, AST* args) {
+ AST* node = ast(AST_APPLY);
+ node->value.apply.func = func;
+ node->value.apply.args = args;
+ return node;
+}
+
+AST* apply_func(AST* apply) {
+ assert(apply->nodetype == AST_APPLY);
+ return apply->value.apply.func;
+}
+
+AST* apply_args(AST* apply) {
+ assert(apply->nodetype == AST_APPLY);
+ return apply->value.apply.args;
+}
}
}
}
+
+void lexprintpos(Parser* p, FILE* file, Tok* tok) {
+ size_t line = 1;
+ char* data = p->file->fbeg;
+ char* end = data + tok->offset;
+ for (; *data && data < end; data++) {
+ if (*data == '\n') line++;
+ }
+ fprintf(file, "%s:%zu: ", tok->file, line);
+}
Tok* tok = peek(parser);
va_list args;
va_start(args, fmt);
- fprintf(stderr, "<file>:%zu: error: ", tok->offset);
+ lexprintpos(parser, stderr, tok);
+ fprintf(stderr, " error: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
}
expect(p, ')');
AST* type = type_expression(p);
- expression_block(p);
- return Var(str, NULL, type, SF_CONSTANT);
+ AST* body = expression_block(p);
+ return Var(str, body, type, SF_CONSTANT);
}
static AST* expression(Parser* p) {
}
/* determine if this is a function call */
- if (matches(p, '(')) { // TODO
- func_expr_list(p);
+ if (matches(p, '(')) {
+ exp = Apply(exp, func_expr_list(p));
} else if (accept(p, '.')) {
- identifier(p);
- func_expr_list(p);
+ AST* func = identifier(p);
+ AST* args = func_expr_list(p);
+ explist_prepend(args, exp);
+ exp = Apply(func, args);
}
return exp;
AST* tree = NULL;
Tok* tok = peek(p);
switch (tok->type) {
- case T_BOOL: tree = Bool(tok);
- case T_CHAR: tree = Char(tok);
- case T_STRING: tree = String(tok);
- case T_INT: tree = Integer(tok);
- case T_FLOAT: tree = Float(tok);
- case T_ID: tree = Ident(tok);
+ case T_BOOL: tree = Bool(tok); break;
+ case T_CHAR: tree = Char(tok); break;
+ case T_STRING: tree = String(tok); break;
+ case T_INT: tree = Integer(tok); break;
+ case T_FLOAT: tree = Float(tok); break;
+ case T_ID: tree = Ident(tok); break;
default: error(p, "expected an expression");
}
accept(p, tok->type);
****************************************************************************/
static AST* expression_block(Parser* p) {
expect(p, '{');
+ AST* list = ExpList();
while (!matches(p, '}')) {
+ AST* expr = 0;
if (matches(p, T_LET) || matches(p, T_VAR)) {
- definition(p);
+ expr = definition(p);
} else if (matches(p, T_FUN)) {
- func_definition(p);
+ expr = func_definition(p);
} else {
- expression(p);
+ expr = expression(p);
}
+ explist_append(list, expr);
}
expect(p, '}');
- return NULL;
+ return list;
}
static AST* if_expression(Parser* p) {
+ AST *cond = 0, *b1 = 0, *b2 = 0;
expect(p, T_IF);
- expression(p); // condition
- expression(p); // true branch
+ cond = expression(p); // condition
+ b1 = expression(p); // true branch
if (accept(p, T_ELSE)) {
- expression(p); // false branch
+ b2 = expression(p); // false branch
}
- return NULL;
+ return If(cond, b1, b2);
}
static AST* identifier(Parser* p) {
static AST* func_expr_list(Parser* p) {
expect(p, '(');
- if (!matches(p, ')')) {
- while (true) {
- expression(p);
- if (!matches(p, ')'))
- expect(p, ',');
- else
- break;
- }
+ AST* list = ExpList();
+ while (!matches(p, ')')) {
+ explist_append(list, expression(p));
+ if (!matches(p, ')'))
+ expect(p, ',');
}
expect(p, ')');
- return NULL;
+ return list;
}
/* AST Types
*****************************************************************************/
typedef enum {
- AST_VAR, AST_FUNC, AST_EXPLIST, AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT,
+ AST_VAR, AST_FUNC, AST_EXPLIST, AST_IF, AST_APPLY,
+ AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT,
AST_FLOAT, AST_BOOL, AST_IDENT
} ASTType;
size_t nexprs;
struct AST** exprs;
} explist;
+ /* If Expression Node */
+ struct {
+ struct AST* cond;
+ struct AST* b1;
+ struct AST* b2;
+ } ifexp;
+ /* Application Node */
+ struct {
+ struct AST* func;
+ struct AST* args;
+ } apply;
/* String, Symbol, Identifier */
char* text;
/* Character */
AST* func_args(AST* func);
AST* func_body(AST* func);
-AST* ExpList(size_t nexprs, AST** exprs);
-AST** explist_get(size_t* nexprs);
+AST* ExpList(void);
+AST** explist_get(AST* explist, size_t* nexprs);
+void explist_append(AST* explist, AST* expr);
+void explist_prepend(AST* explist, AST* expr);
+
+AST* If(AST* cond, AST* b1, AST* b2);
+AST* if_cond(AST* ifexp);
+AST* if_then(AST* ifexp);
+AST* if_else(AST* ifexp);
+
+AST* Apply(AST* func, AST* args);
+AST* apply_func(AST* apply);
+AST* apply_args(AST* apply);
/* Package Definition
*****************************************************************************/
void lexfile(Parser* ctx, char* path);
void lex(Parser* ctx);
+void lexprintpos(Parser* p, FILE* file, Tok* tok);
void gettoken(Parser* ctx);
void toplevel(Parser* p);
void codegen_init(Parser* p);