Skip to content

Commit

Permalink
add when
Browse files Browse the repository at this point in the history
  • Loading branch information
graphitemaster committed Jul 29, 2023
1 parent 637b3b2 commit 89c1124
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 18 deletions.
35 changes: 31 additions & 4 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Bool dump_compound_literal_expression(const CompoundLiteralExpression *expressio

Bool dump_identifier_expression(const IdentifierExpression *expression, Sint32 depth) {
pad(depth);
printf("'(ident %.*s')", SFMT(expression->identifier->contents));
printf("(ident '%.*s')", SFMT(expression->identifier->contents));
return true;
}

Expand Down Expand Up @@ -276,8 +276,16 @@ Bool dump_matrix_type(const MatrixType *type, Sint32 depth) {
return true;
}

Bool dump_distinct_type(const DistinctType *type, Sint32 depth) {
pad(depth);
printf("(distinct\n");
dump_type(type->type, depth + 1);
printf(")");
return true;
}

Bool dump_expression_type(const ExpressionType *type, Sint32 depth) {
return type->expression ? dump_expression(type->expression, depth) : false;
return dump_expression(type->expression, depth);
}

Bool dump_procedure_expression(const ProcedureExpression *expression, Sint32 depth) {
Expand Down Expand Up @@ -311,6 +319,7 @@ Bool dump_type(const Type *type, Sint32 depth) {
case TYPE_TYPEID: return dump_typeid_type(RCAST(const TypeidType *, type), depth);
case TYPE_MAP: return dump_map_type(RCAST(const MapType *, type), depth);
case TYPE_MATRIX: return dump_matrix_type(RCAST(const MatrixType *, type), depth);
case TYPE_DISTINCT: return dump_distinct_type(RCAST(const DistinctType *, type), depth);
case TYPE_EXPRESSION: return dump_expression_type(RCAST(const ExpressionType *, type), depth);
}
return false;
Expand Down Expand Up @@ -377,8 +386,9 @@ Bool dump_expression(const Expression *expression, Sint32 depth) {

Bool dump_block_statement(const BlockStatement *statement, Sint32 depth) {
pad(depth);
printf("(block\n");
printf("(block");
if (statement->flags) {
printf("\n");
const String flags = block_flags_to_string(statement->flags);
pad(depth + 1);
printf("(flags %.*s)", SFMT(flags));
Expand Down Expand Up @@ -425,7 +435,9 @@ Bool dump_declaration_statement(const DeclarationStatement *statement, Sint32 de
for (Uint64 i = 0; i < n_names; i++) {
const Identifier *name = statement->names[i];
pad(depth);
printf("(decl '%.*s'", SFMT(name->contents));
printf("(decl\n");
pad(depth + 1);
printf("'%.*s'", SFMT(name->contents));
if (statement->type) {
printf("\n");
dump_type(statement->type, depth + 1);
Expand Down Expand Up @@ -462,6 +474,20 @@ Bool dump_if_statement(const IfStatement *statement, Sint32 depth) {
return true;
}

Bool dump_when_statement(const WhenStatement *statement, Sint32 depth) {
pad(depth);
printf("(when\n");
dump_expression(statement->cond, depth + 1);
printf("\n");
dump_block_statement(statement->body, depth + 1);
if (statement->elif) {
printf("\n");
dump_block_statement(statement->elif, depth + 1);
}
printf(")");
return true;
}

Bool dump_return_statement(const ReturnStatement *statement, Sint32 depth) {
pad(depth);
printf("(ret");
Expand Down Expand Up @@ -529,6 +555,7 @@ Bool dump_statement(const Statement *statement, Sint32 depth) {
case STATEMENT_ASSIGNMENT: return dump_assignment_statement(RCAST(const AssignmentStatement *, statement), depth);
case STATEMENT_DECLARATION: return dump_declaration_statement(RCAST(const DeclarationStatement *, statement), depth);
case STATEMENT_IF: return dump_if_statement(RCAST(const IfStatement *, statement), depth);
case STATEMENT_WHEN: return dump_when_statement(RCAST(const WhenStatement *, statement), depth);
case STATEMENT_RETURN: return dump_return_statement(RCAST(const ReturnStatement *, statement), depth);
case STATEMENT_FOR: return dump_for_statement(RCAST(const ForStatement *, statement), depth);
case STATEMENT_DEFER: return dump_defer_statement(RCAST(const DeferStatement *, statement), depth);
Expand Down
80 changes: 76 additions & 4 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,20 @@ static TypeExpression *parse_operand_slice_type_expression(Parser *parser) {
return expression;
}

// distinct T
static TypeExpression *parse_operand_distinct_type(Parser *parser) {
TRACE_ENTER();

expect_keyword(parser, KEYWORD_DISTINCT);

DistinctType *type = tree_new_distinct_type(parser->tree, parse_type(parser));
TypeExpression *expression = tree_new_type_expression(parser->tree, RCAST(Type *, type));

TRACE_LEAVE();

return expression;
}

// $ident
static IdentifierExpression *parse_operand_const_identifier_expression(Parser *parser) {
TRACE_ENTER();
Expand Down Expand Up @@ -980,7 +994,11 @@ static Expression *parse_operand(Parser *parser, Bool lhs) {
case KIND_KEYWORD:
switch (token.as_keyword) {
case KEYWORD_DISTINCT:
UNIMPLEMENTED("distinct");
{
TypeExpression *expression = parse_operand_distinct_type(parser);
TRACE_LEAVE();
return RCAST(Expression *, expression);
}
case KEYWORD_PROC:
{
Expression *expression = 0;
Expand Down Expand Up @@ -1023,8 +1041,6 @@ static Expression *parse_operand(Parser *parser, Bool lhs) {
UNIMPLEMENTED("union");
case KEYWORD_ENUM:
UNIMPLEMENTED("enum");
case KEYWORD_ASM:
UNIMPLEMENTED("asm");
case KEYWORD_CONTEXT:
UNIMPLEMENTED("context");
default:
Expand Down Expand Up @@ -1882,6 +1898,58 @@ static IfStatement *parse_if_statement(Parser *parser, BlockFlag block_flags) {
return statement;
}

static WhenStatement *parse_when_statement(Parser *parser) {
Context *context = parser->context;

TRACE_ENTER();

expect_keyword(parser, KEYWORD_WHEN);

const Sint32 expression_depth = parser->expression_depth;
parser->expression_depth = -1;

Expression *cond = parse_expression(parser, false);

parser->expression_depth = expression_depth;

if (!cond) {
PARSE_ERROR("Expected condition in 'when' statement");
}

BlockStatement *body = 0;
const BlockFlag flags = CAST(BlockFlag, 0);
if (accepted_keyword(parser, KEYWORD_DO)) {
body = parse_do_body(parser, flags);
} else {
body = parse_block_statement(parser, flags, true);
}

advance_possible_newline_within(parser);

BlockStatement *elif = 0;
if (is_keyword(parser->this_token, KEYWORD_ELSE)) {
expect_keyword(parser, KEYWORD_ELSE);
if (is_keyword(parser->this_token, KEYWORD_WHEN)) {
WhenStatement *statement = parse_when_statement(parser);
Array(Statement) *statements = 0;
array_push(statements, RCAST(Statement *, statement));
elif = tree_new_block_statement(parser->tree, flags, statements);
} else if (is_keyword(parser->this_token, KEYWORD_DO)) {
elif = parse_do_body(parser, flags);
} else if (is_kind(parser->this_token, KIND_LBRACE)) {
elif = parse_block_statement(parser, flags, true);
} else {
PARSE_ERROR("Unexpected statement in 'when' else block");
}
}

WhenStatement *statement = tree_new_when_statement(parser->tree, cond, body, elif);

TRACE_LEAVE();

return CAST(BlockStatement *, statement);
}

static ForStatement *parse_for_statement(Parser *parser, BlockFlag block_flags) {
TRACE_ENTER();

Expand Down Expand Up @@ -2104,7 +2172,11 @@ static Statement *parse_statement(Parser *parser, BlockFlag block_flags) {
return RCAST(Statement *, statement);
}
case KEYWORD_WHEN:
UNIMPLEMENTED("when");
{
WhenStatement *statement = parse_when_statement(parser);
TRACE_LEAVE();
return RCAST(Statement *, statement);
}
case KEYWORD_IMPORT:
{
ImportStatement *statement = parse_import_statement(parser);
Expand Down
19 changes: 19 additions & 0 deletions src/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,16 @@ IfStatement *tree_new_if_statement(Tree *tree, Statement *init, Expression *cond
return statement;
}

WhenStatement *tree_new_when_statement(Tree *tree, Expression *cond, BlockStatement *body, BlockStatement *elif) {
Allocator *allocator = tree->context->allocator;
WhenStatement *statement = CAST(WhenStatement *, allocator->allocate(allocator, sizeof *statement));
statement->base.kind = STATEMENT_WHEN;
statement->body = body;
statement->cond = cond;
statement->elif = elif;
return statement;
}

ForStatement *tree_new_for_statement(Tree *tree, Statement *init, Expression *cond, BlockStatement *body, Statement *post) {
Allocator *allocator = tree->context->allocator;
ForStatement *statement = CAST(ForStatement *, allocator->allocate(allocator, sizeof *statement));
Expand Down Expand Up @@ -338,6 +348,15 @@ MatrixType *tree_new_matrix_type(Tree *tree, Expression *rows, Expression *colum
return type;
}

// distinct T
DistinctType *tree_new_distinct_type(Tree *tree, Type *base_type) {
Allocator *allocator = tree->context->allocator;
DistinctType *type = CAST(DistinctType *, allocator->allocate(allocator, sizeof *type));
type->base.kind = TYPE_DISTINCT;
type->type = base_type;
return type;
}

ExpressionType *tree_new_expression_type(Tree *tree, Expression *expression) {
Allocator *allocator = tree->context->allocator;
ExpressionType *type = CAST(ExpressionType *, allocator->allocate(allocator, sizeof *type));
Expand Down
18 changes: 18 additions & 0 deletions src/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef struct BlockStatement BlockStatement;
typedef struct AssignmentStatement AssignmentStatement;
typedef struct DeclarationStatement DeclarationStatement;
typedef struct IfStatement IfStatement;
typedef struct WhenStatement WhenStatement;
typedef struct ReturnStatement ReturnStatement;
typedef struct ForStatement ForStatement;
typedef struct DeferStatement DeferStatement;
Expand All @@ -56,6 +57,7 @@ typedef struct BitSetType BitSetType;
typedef struct TypeidType TypeidType;
typedef struct MapType MapType;
typedef struct MatrixType MatrixType;
typedef struct DistinctType DistinctType;
typedef struct ExpressionType ExpressionType;

// Misc.
Expand Down Expand Up @@ -88,6 +90,7 @@ enum StatementKind {
STATEMENT_ASSIGNMENT,
STATEMENT_DECLARATION,
STATEMENT_IF,
STATEMENT_WHEN,
STATEMENT_RETURN,
STATEMENT_FOR,
STATEMENT_DEFER,
Expand All @@ -112,6 +115,7 @@ enum TypeKind {
TYPE_TYPEID, // typeid
TYPE_MAP, // map[K]V
TYPE_MATRIX, // matrix[R,C]T
TYPE_DISTINCT, // distinct T
TYPE_EXPRESSION, // Expression which evaluates to a Type*
};

Expand Down Expand Up @@ -338,6 +342,13 @@ struct IfStatement {
BlockStatement *elif;
};

struct WhenStatement {
Statement base;
Expression *cond;
BlockStatement *body;
BlockStatement *elif;
};

struct ReturnStatement {
Statement base;
Array(Expression*) results;
Expand Down Expand Up @@ -449,6 +460,11 @@ struct MatrixType {
Type *type;
};

struct DistinctType {
Type base;
Type *type;
};

struct ExpressionType {
Type base;
// Can be one of:
Expand Down Expand Up @@ -511,6 +527,7 @@ BlockStatement *tree_new_block_statement(Tree *tree, BlockFlag flags, Array(Stat
AssignmentStatement *tree_new_assignment_statement(Tree *tree, AssignmentKind assignment, ListExpression *lhs, ListExpression *rhs);
DeclarationStatement *tree_new_declaration_statement(Tree *tree, Type *type, Array(Identifier*) names, ListExpression *values);
IfStatement *tree_new_if_statement(Tree *tree, Statement *init, Expression *cond, BlockStatement *body, BlockStatement *elif);
WhenStatement *tree_new_when_statement(Tree *tree, Expression *cond, BlockStatement *body, BlockStatement *elif);
ForStatement *tree_new_for_statement(Tree *tree, Statement *init, Expression *cond, BlockStatement *body, Statement *post);
ReturnStatement *tree_new_return_statement(Tree *tree, Array(Expression*) results);
DeferStatement *tree_new_defer_statement(Tree *tree, Statement *stmt);
Expand All @@ -530,6 +547,7 @@ BitSetType *tree_new_bit_set_type(Tree *tree, Expression *expression, Type *unde
TypeidType *tree_new_typeid_type(Tree *tree, Type *specialization);
MapType *tree_new_map_type(Tree *tree, Type *key, Type *value);
MatrixType *tree_new_matrix_type(Tree *tree, Expression *rows, Expression *columns, Type *type);
DistinctType *tree_new_distinct_type(Tree *tree, Type *type);
ExpressionType *tree_new_expression_type(Tree *tree, Expression *expression);

Field *tree_new_field(Tree *tree, Type *type, Identifier *name, Expression *value);
Expand Down
14 changes: 4 additions & 10 deletions tests/main.odin
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

// TODO:
// distinct
// struct, union, enum
// attributes (@static, @private, etc)
// switch
Expand All @@ -12,13 +11,8 @@ package main

import "core:fmt"

e :: proc() -> (x: [2]int) {
return {};
}

b :: proc(x: int) {
e := 0;
{
f := 0;
}
when true {
x := 10
} else {
y := 20
}

0 comments on commit 89c1124

Please sign in to comment.