# flags
INCS = -Isource/
CPPFLAGS = -D_XOPEN_SOURCE=700
-CFLAGS += ${INCS} ${CPPFLAGS} -Wall -Wextra
+CFLAGS += ${INCS} ${CPPFLAGS}
LDFLAGS += ${LIBS}
#------------------------------------------------------------------------------
break;
case AST_FUNC:
- //vec_deinit(&(ast->value.func.args));
+ vec_deinit(&(ast->value.func.args));
gc_delref(ast->value.func.body);
break;
func->value.func.body = (AST*)gc_addref(body);
}
+AST* FnApp(AST* fn)
+{
+ AST* node = ast(AST_FNAPP);
+ node->value.fnapp.fn = (AST*)gc_addref(fn);
+ vec_init(&(node->value.fnapp.args));
+ return node;
+}
+
+void fnapp_add_arg(AST* func, AST* arg)
+{
+ vec_push_back(&(func->value.fnapp.args), gc_addref(arg));
+}
+
//AST* Ann(char* name, AST* value)
//{
static AST* literal(Parser* p);
static AST* expr_block(Parser* p);
static AST* token_to_tree(Tok* tok);
+static AST* func_app(Parser* p, AST* fn);
AST* toplevel(Parser* p)
{
static AST* expression(Parser* p)
{
+ AST* expr = NULL;
if (accept(p, T_LPAR)) {
- AST* expr = expression(p);
+ expr = expression(p);
expect(p, T_RPAR);
- return expr;
} else if (accept_str(p, T_ID, "if")) {
- return if_stmnt(p);
+ expr = if_stmnt(p);
} else if (accept_str(p, T_ID, "fn")) {
- return function(p);
+ expr = function(p);
} else if (match(p, T_ID)) {
- return Ident(expect(p,T_ID));
- //if (peek(p)->type == T_LPAR) {
- // arglist(p);
- //}
+ expr = Ident(expect(p,T_ID));
} else {
- return literal(p);
+ expr = literal(p);
}
+ /* Check if this is a function application */
+ if (peek(p)->type == T_LPAR) {
+ expr = func_app(p, expr);
+ }
+ return expr;
}
static AST* if_stmnt(Parser* p)
}
}
-
+static AST* func_app(Parser* p, AST* fn)
+{
+ AST* app = FnApp(fn);
+ expect(p,T_LPAR);
+ while (peek(p)->type != T_RPAR) {
+ fnapp_add_arg(p, expression(p));
+ if (peek(p)->type != T_RPAR)
+ expect(p, T_COMMA);
+ }
+ expect(p,T_RPAR);
+ return app;
+}
#if 0
-
-static AST* require(Parser* p);
-static AST* type_annotation(Parser* p);
-static AST* type_definition(Parser* p);
-static AST* type(Parser* p);
-static AST* tuple(Parser* p);
-static AST* function(Parser* p);
-static AST* definition(Parser* p);
-static AST* expression(Parser* p);
-static AST* arglist(Parser* p);
-static AST* if_stmnt(Parser* p);
-static AST* fn_stmnt(Parser* p);
-
-
static AST* type_annotation(Parser* p)
{
//shifttok(p, T_ID);
return NULL;
}
-/*****************************************************************************/
-
static AST* type_definition(Parser* p)
{
//expect(p, T_ID);
////reduce(p, mrk);
return NULL;
}
-
-static AST* function(Parser* p) {
- ////size_t mark1 = mark(p) - 1;
- ////size_t mark2 = mark(p);
- //while (!accept(p, T_RPAR)) {
- // type(p);
- // if (T_RPAR != peek(p)->type)
- // expect(p, T_COMMA);
- //}
- ////reduce(p, mark2);
- ////reduce(p, mark1);
- return NULL;
-}
-
-static AST* arglist(Parser* p)
-{
- ////size_t mrk = mark(p);
- //expect(p, T_LPAR);
- //while(peek(p)->type != T_RPAR) {
- // expression(p);
- // if(peek(p)->type != T_RPAR)
- // expect(p, T_COMMA);
- //}
- //expect(p, T_RPAR);
- ////reduce(p, mrk);
- return NULL;
-}
-
-
-
#endif
*****************************************************************************/
typedef enum ASTType {
AST_STRING = 0, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT,
- AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_BLOCK
+ AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_FNAPP, AST_BLOCK
} ASTType;
typedef struct AST {
vec_t args;
struct AST* body;
} func;
+ /* Function Application */
+ struct {
+ struct AST* fn;
+ vec_t args;
+ } fnapp;
/* Code Block */
vec_t exprs;
/* String, Symbol, Identifier */
void func_add_arg(AST* func, AST* arg);
void func_set_body(AST* func, AST* body);
+/* Function Application */
+AST* FnApp(AST* fn);
+void fnapp_add_arg(AST* func, AST* arg);
+
///* Annotation */
//AST* Ann(char* name, AST* value);
//char* ann_name(AST* def);
//AST* ann_value(AST* def);
-//
-//
-//
-//
+
/* Lexer and Parser Types
*****************************************************************************/
typedef struct {
end
end
-# context "function application" do
-# it "should parse an application with no params " do
-# expect(ast('foo()')).to eq([["T_ID:foo"]])
-# end
-#
-# it "should parse an application with one param" do
-# expect(ast('foo(a)')).to eq([["T_ID:foo", "T_ID:a"]])
-# end
-#
-# it "should parse an application with two params" do
-# expect(ast('foo(a,b)')).to eq([["T_ID:foo", "T_ID:a", "T_ID:b"]])
-# end
-# end
+ context "function application" do
+ it "should parse an application with no params " do
+ expect(ast('foo()')).to eq([["T_ID:foo"]])
+ end
+
+ it "should parse an application with one param" do
+ expect(ast('foo(a)')).to eq([["T_ID:foo", "T_ID:a"]])
+ end
+
+ it "should parse an application with two params" do
+ expect(ast('foo(a,b)')).to eq([["T_ID:foo", "T_ID:a", "T_ID:b"]])
+ end
+ end
end
context "corner cases" do