diff --git a/projects/functions.j b/projects/functions.j new file mode 100644 index 0000000..07fc53f --- /dev/null +++ b/projects/functions.j @@ -0,0 +1,11 @@ +x = "Hello world!" +y = 21 +println() +println(x) +print("y=") +println(y) + +dummy() + +if y > 1: + println("OK!") \ No newline at end of file diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h index 85476db..9a7598e 100644 --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.h @@ -15,8 +15,6 @@ typedef enum { // Identificadores y keywords TOK_ID, // x, foo, mi_var - TOK_PRINT, // print - TOK_PRINTLN, // println TOK_IF, // if TOK_WHILE, // while @@ -35,6 +33,7 @@ typedef enum { TOK_LPAREN, // ( TOK_RPAREN, // ) TOK_COLON, // : + TOK_COMMA, // , TOK_NEWLINE, // \n (significativo, como en Python) TOK_INDENT, // aumento de indentacion TOK_DEDENT, // reduccion de indentacion @@ -118,6 +117,15 @@ Token *tokenize(const char *source, int *token_count) { } else if (c == ':') { tokens[count++] = make_token(TOK_COLON, ":"); pos++; + } else if (c == ',') { + tokens[count++] = make_token(TOK_COMMA, ","); + pos++; + } else if (c == '(') { + tokens[count++] = make_token(TOK_LPAREN, "("); + pos++; + } else if (c == ')') { + tokens[count++] = make_token(TOK_RPAREN, ")"); + pos++; } else if (c == '"') { // Leer todo hasta el proximo '"' pos++; // consumir '"' @@ -138,16 +146,13 @@ Token *tokenize(const char *source, int *token_count) { while (isalnum(source[pos])) pos++; char *word = substr(source, start, pos); + // tokens[count++] = make_token(TOK_ID, word); // Comprobar si es una keyword reservada - if (strcmp(word, "print") == 0) { - tokens[count++] = make_token(TOK_PRINT, word); + if (strcmp(word, "if") == 0) { + tokens[count++] = make_token(TOK_IF, word); } else if (strcmp(word, "while") == 0) { tokens[count++] = make_token(TOK_WHILE, word); - } else if (strcmp(word, "if") == 0) { - tokens[count++] = make_token(TOK_IF, word); - } else if (strcmp(word, "println") == 0) { - tokens[count++] = make_token(TOK_PRINTLN, word); } else { tokens[count++] = make_token(TOK_ID, word); } diff --git a/src/frontend/parser.h b/src/frontend/parser.h index dc4297e..0ff71bf 100644 --- a/src/frontend/parser.h +++ b/src/frontend/parser.h @@ -17,6 +17,7 @@ typedef enum { NODE_IF, // if cond: bloque NODE_WHILE, // while cond: bloque NODE_BLOCK, // secuencia de statements + NODE_CALL, } NodeType; typedef struct ASTNode { @@ -48,6 +49,11 @@ typedef struct ASTNode { struct ASTNode *cond; struct ASTNode *body; } if_statement; // NODE_IF + struct { + char *name; + struct ASTNode **args; + int arg_count; + } call; } data; } ASTNode; @@ -71,10 +77,13 @@ ASTNode *parse_term(Token *tokens) { pos++; return node; } else if (tokens[pos].type == TOK_ID) { + printf("Parsing token: %s\n", tokens[pos].value); + ASTNode *node = make_node(NODE_VAR); node->data.string_val = tokens[pos].value; pos++; return node; + } else if (tokens[pos].type == TOK_MINUS) { pos++; // consumir '-' ASTNode *term = parse_term(tokens); @@ -85,7 +94,9 @@ ASTNode *parse_term(Token *tokens) { neg->data.binop.right = term; return neg; } - printf("ERROR: esperaba INT o ID, encontre tipo %d\n", tokens[pos].type); + + printf("ERROR: esperaba INT o ID, encontre tipo %d value: %s\n", + tokens[pos].type, tokens[pos].value); exit(1); } @@ -110,6 +121,32 @@ ASTNode *parse_expr(Token *tokens) { ASTNode *parse_statement(Token *tokens) { if (tokens[pos].type == TOK_ID) { + if (tokens[pos + 1].type == TOK_LPAREN) { + // Es una funcion + char *name = tokens[pos].value; + pos++; // consumir ID + pos++; // consumir "(" + + // Parsear argumentos + ASTNode **args = + (ASTNode **)malloc(sizeof(ASTNode *) * 16); // Max 16 parametros + int arg_count = 0; + + if (tokens[pos].type != TOK_RPAREN) { + args[arg_count++] = parse_expr(tokens); + while (tokens[pos].type == TOK_COMMA) { + pos++; // Consumir "," + args[arg_count++] = parse_expr(tokens); + } + } + pos++; // consumir ")" + ASTNode *node = make_node(NODE_CALL); + node->data.call.name = name; + node->data.call.args = args; + node->data.call.arg_count = arg_count; + return node; + } + char *name = tokens[pos].value; pos++; // consumir ID pos++; // consumir "=" @@ -120,23 +157,6 @@ ASTNode *parse_statement(Token *tokens) { node->data.assign.value = value; return node; } - if (tokens[pos].type == TOK_PRINT) { - pos++; // consumir "print" - ASTNode *expr = parse_expr(tokens); - - ASTNode *node = make_node(NODE_PRINT); - node->data.print.expr = expr; - return node; - } - - if (tokens[pos].type == TOK_PRINTLN) { - pos++; // consumir "println" - ASTNode *expr = parse_expr(tokens); - - ASTNode *node = make_node(NODE_PRINTLN); - node->data.print.expr = expr; - return node; - } if (tokens[pos].type == TOK_WHILE) { pos++; // consumir while @@ -257,16 +277,6 @@ void ast_print(ASTNode *node, const char *prefix, int is_last) { ast_print(node->data.binop.right, new_prefix, 1); break; - case NODE_PRINT: - printf("NODE_PRINT\n"); - ast_print(node->data.print.expr, new_prefix, 1); - break; - - case NODE_PRINTLN: - printf("NODE_PRINTLN\n"); - ast_print(node->data.print.expr, new_prefix, 1); - break; - case NODE_BLOCK: printf("NODE_BLOCK\n"); for (int i = 0; i < node->data.block.count; i++) { @@ -281,6 +291,14 @@ void ast_print(ASTNode *node, const char *prefix, int is_last) { ast_print(node->data.while_loop.body, new_prefix, 1); break; + case NODE_CALL: + printf("NODE_CALL(\"%s\")\n", node->data.call.name); + for (int i = 0; i < node->data.call.arg_count; i++) { + ast_print(node->data.call.args[i], new_prefix, + i == node->data.call.arg_count - 1); + } + break; + default: printf("UNKNOWN\n"); break; diff --git a/src/vm/eval.h b/src/vm/eval.h index 0f04d85..aee01f5 100644 --- a/src/vm/eval.h +++ b/src/vm/eval.h @@ -83,7 +83,8 @@ size_t eval(ASTNode *node, Environment *env, void *allocator, int debug, l->data.string_val.length); // Copy right text - memcpy(tempBuff + l->data.string_val.length, JLANG_RESOLVE(allocator, r->data.string_val.chars), + memcpy(tempBuff + l->data.string_val.length, + JLANG_RESOLVE(allocator, r->data.string_val.chars), r->data.string_val.length); tempBuff[n] = '\0'; @@ -145,6 +146,31 @@ size_t eval(ASTNode *node, Environment *env, void *allocator, int debug, } break; } + case NODE_CALL: { + if (strcmp(node->data.call.name, "print") == 0) { + if (node->data.call.arg_count > 0) { + size_t val = eval(node->data.call.args[0], env, allocator, debug, gc); + obj_print(allocator, val, ""); + return val; + } + + printf(""); + return 0; + } + if (strcmp(node->data.call.name, "println") == 0) { + if (node->data.call.arg_count > 0) { + size_t val = eval(node->data.call.args[0], env, allocator, debug, gc); + obj_print(allocator, val, ""); + printf("\n"); + return val; + } + + printf("\n"); + return 0; + } + printf("ERROR: funcion '%s' no definida\n", node->data.call.name); + exit(1); + } default: break; }