Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions ezc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $(BIN): $(OBJ)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

clean:
rm -f $(OBJ) $(BIN) tests/test_lexer tests/test_parser
rm -f $(OBJ) $(BIN) tests/test_lexer tests/test_parser tests/test_typechecker tests/test_codegen

install: build
install -d /usr/local/bin
Expand All @@ -73,14 +73,27 @@ tests/test_lexer: tests/test_lexer.c $(TEST_DEPS)
tests/test_parser: tests/test_parser.c $(TEST_DEPS)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS)

test-unit: $(TEST_DEPS) tests/test_lexer tests/test_parser
tests/test_typechecker: tests/test_typechecker.c $(TEST_DEPS)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS)

tests/test_codegen: tests/test_codegen.c
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< $(LDFLAGS)

test-unit: $(TEST_DEPS) tests/test_lexer tests/test_parser tests/test_typechecker
@echo ""
@echo "=== Lexer Tests ==="
@./tests/test_lexer
@echo "=== Parser Tests ==="
@./tests/test_parser
@echo "=== Type Checker Tests ==="
@./tests/test_typechecker

test-e2e: build tests/test_codegen
@echo ""
@echo "=== End-to-End Codegen Tests ==="
@./tests/test_codegen

test-parity: build
@./tests/run_parity.sh

test: test-unit test-parity
test: test-unit test-e2e test-parity
23 changes: 21 additions & 2 deletions ezc/src/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,15 +683,34 @@ static AstNode *parse_func_declaration(Parser *p) {
* -> (int, string) plain types
* -> (x int, y int) named returns
* -> (x, y int) shared type
*
* Disambiguation: if the identifier is a known type name,
* it's a plain type list, not names.
*/
next_token(p);
while (!cur_token_is(p, TOK_RPAREN) && !cur_token_is(p, TOK_EOF)) {
if (cur_token_is(p, TOK_IDENT) && peek_token_is(p, TOK_IDENT)) {
/* Check if current ident is a type name (not a variable name) */
bool is_type = false;
if (cur_token_is(p, TOK_IDENT)) {
const char *lit = p->cur_token.literal;
is_type = (strcmp(lit, "int") == 0 || strcmp(lit, "uint") == 0 ||
strcmp(lit, "i8") == 0 || strcmp(lit, "i16") == 0 ||
strcmp(lit, "i32") == 0 || strcmp(lit, "i64") == 0 ||
strcmp(lit, "u8") == 0 || strcmp(lit, "u16") == 0 ||
strcmp(lit, "u32") == 0 || strcmp(lit, "u64") == 0 ||
strcmp(lit, "float") == 0 || strcmp(lit, "f32") == 0 ||
strcmp(lit, "f64") == 0 || strcmp(lit, "string") == 0 ||
strcmp(lit, "bool") == 0 || strcmp(lit, "char") == 0 ||
strcmp(lit, "byte") == 0 ||
(lit[0] >= 'A' && lit[0] <= 'Z')); /* struct/enum types */
}

if (cur_token_is(p, TOK_IDENT) && peek_token_is(p, TOK_IDENT) && !is_type) {
/* Named return: name type — skip name, use type */
next_token(p);
node->data.func_decl.return_types[node->data.func_decl.return_type_count++] =
p->cur_token.literal;
} else if (cur_token_is(p, TOK_IDENT) && peek_token_is(p, TOK_COMMA)) {
} else if (cur_token_is(p, TOK_IDENT) && peek_token_is(p, TOK_COMMA) && !is_type) {
/* Shared type: (x, y int) — count names, assign same type to all */
int shared = 1;
while (peek_token_is(p, TOK_COMMA)) {
Expand Down
Loading
Loading