diff --git a/asm/assembler/assembler.c b/asm/assembler/assembler.c index cc80028..f6f8ee1 100644 --- a/asm/assembler/assembler.c +++ b/asm/assembler/assembler.c @@ -1,18 +1,20 @@ +#include "assembler.h" + +#include #include #include -#include +#include #include #include -#include - -#include "assembler.h" extern struct assembler_scope_type class_scope_type; extern struct assembler_scope_type constpool_scope_type; +extern struct assembler_scope_type block_scope_type; static const struct assembler_scope_type *scope_types[] = { [IVY_ASM_SCOPE_CLASS] = &class_scope_type, [IVY_ASM_SCOPE_CONSTPOOL] = &constpool_scope_type, + [IVY_ASM_SCOPE_BLOCK] = &block_scope_type, }; static const size_t nr_scope_types = sizeof scope_types / sizeof scope_types[0]; @@ -24,7 +26,7 @@ struct asm_table_entry { struct ivy_assembler { struct assembler_scope *as_scope; b_queue as_table; - + FILE *as_data; size_t as_data_offset; @@ -35,7 +37,7 @@ struct ivy_assembler { enum ivy_status ivy_assembler_create(FILE *fp, struct ivy_assembler **as) { struct ivy_assembler *out = malloc(sizeof *out); - + if (!out) { return IVY_ERR_NO_MEMORY; } @@ -47,7 +49,7 @@ enum ivy_status ivy_assembler_create(FILE *fp, struct ivy_assembler **as) struct ivy_bin_header header = {0}; header.h_magic = b_i32_htob(0xAABBCCDD); - + fseek(fp, 0, SEEK_SET); fwrite(&header, sizeof header, 1, fp); out->as_data_offset = sizeof header; @@ -71,7 +73,7 @@ enum ivy_status ivy_assembler_finish(struct ivy_assembler *as) { const size_t buf_len = 4096; size_t xdat_len = as->as_next_xdata_key; - + fseek(as->as_xdat, 0, SEEK_SET); unsigned char *buf = malloc(buf_len); @@ -116,7 +118,8 @@ enum ivy_status ivy_assembler_finish(struct ivy_assembler *as) b_queue_iterator it = {0}; b_queue_foreach (&it, &as->as_table) { - struct asm_table_entry *e = b_unbox(struct asm_table_entry, it.entry, e_entry); + struct asm_table_entry *e + = b_unbox(struct asm_table_entry, it.entry, e_entry); size_t w = fwrite(&e->e_data, 1, sizeof e->e_data, as->as_data); if (w < sizeof e->e_data) { @@ -150,7 +153,8 @@ size_t assembler_write_data(struct ivy_assembler *as, const void *p, size_t len) return offset; } -ivy_extended_data_key assembler_write_extended_data(struct ivy_assembler *as, const void *p, size_t len) +ivy_extended_data_key assembler_write_extended_data( + struct ivy_assembler *as, const void *p, size_t len) { ivy_extended_data_key key = as->as_next_xdata_key; @@ -228,18 +232,17 @@ enum ivy_status ivy_assembler_end_scope(struct ivy_assembler *as) memset(entry, 0x0, sizeof *entry); - entry->e_data.e_offset = b_i64_htob((uint64_t)as->as_scope->s_start_offset); - entry->e_data.e_size = b_i32_htob((uint32_t)(as->as_data_offset - as->as_scope->s_start_offset)); + entry->e_data.e_offset + = b_i64_htob((uint64_t)as->as_scope->s_start_offset); + entry->e_data.e_size = b_i32_htob( + (uint32_t)(as->as_data_offset - as->as_scope->s_start_offset)); switch (as->as_scope->s_type) { case IVY_ASM_SCOPE_CLASS: entry->e_data.e_type = b_i32_htob(IVY_TABLE_CLASS); break; - case IVY_ASM_SCOPE_LAMBDA: - entry->e_data.e_type = b_i32_htob(IVY_TABLE_LAMBDA); - break; - case IVY_ASM_SCOPE_MSGH: - entry->e_data.e_type = b_i32_htob(IVY_TABLE_MSGH); + case IVY_ASM_SCOPE_BLOCK: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_BLOCK); break; case IVY_ASM_SCOPE_CONSTPOOL: entry->e_data.e_type = b_i32_htob(IVY_TABLE_POOL); @@ -310,4 +313,4 @@ enum ivy_status ivy_assembler_put_instr( } return type_info->s_put_instr(as, scope, i); -} \ No newline at end of file +} diff --git a/asm/assembler/msgh.c b/asm/assembler/block.c similarity index 100% rename from asm/assembler/msgh.c rename to asm/assembler/block.c diff --git a/asm/assembler/class.c b/asm/assembler/class.c index c1d8015..9d3d028 100644 --- a/asm/assembler/class.c +++ b/asm/assembler/class.c @@ -1,23 +1,23 @@ #include "assembler.h" + #include -static enum ivy_status init_scope(struct ivy_assembler *as, struct assembler_scope *scope, +static enum ivy_status init_scope( + struct ivy_assembler *as, struct assembler_scope *scope, const ivy_assembler_attrib_table attrib) { struct ivy_bin_class header = {0}; header.c_ident = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_IDENT]); - + assembler_write_data(as, &header, sizeof header); return IVY_OK; } static enum ivy_status put_xval( - struct ivy_assembler *as, - struct assembler_scope *scope, - enum ivy_assembler_xval_type type, - const ivy_assembler_attrib_table attrib) + struct ivy_assembler *as, struct assembler_scope *scope, + enum ivy_assembler_xval_type type, const ivy_assembler_attrib_table attrib) { struct ivy_bin_class_table_entry entry = {0}; switch (type) { @@ -37,10 +37,17 @@ static enum ivy_status put_xval( entry.e_mvar.m_index = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_INDEX]); break; + case IVY_ASM_XVAL_MESSAGE_HANDLER: + entry.e_type = b_i32_htob(IVY_CLASS_TABLE_MSGH); + entry.e_msgh.msg_selector + = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_SELECTOR]); + entry.e_msgh.msg_block + = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_BLOCK]); + break; default: return IVY_ERR_NOT_SUPPORTED; } - + assembler_write_data(as, &entry, sizeof entry); return IVY_OK; } @@ -49,4 +56,4 @@ const struct assembler_scope_type class_scope_type = { .s_scope_size = sizeof(struct assembler_scope), .s_init_scope = init_scope, .s_put_xval = put_xval, -}; \ No newline at end of file +}; diff --git a/asm/assembler/lambda.c b/asm/assembler/lambda.c index e69de29..43d75ea 100644 --- a/asm/assembler/lambda.c +++ b/asm/assembler/lambda.c @@ -0,0 +1,21 @@ +#include "assembler.h" + +#include + +static enum ivy_status init_scope( + struct ivy_assembler *as, struct assembler_scope *scope, + const ivy_assembler_attrib_table attrib) +{ + struct ivy_bin_block header = {0}; + + header.b_index = b_i32_htob((uint32_t)attrib[IVY_ASM_ATTRIB_INDEX]); + + assembler_write_data(as, &header, sizeof header); + + return IVY_OK; +} + +const struct assembler_scope_type block_scope_type = { + .s_scope_size = sizeof(struct assembler_scope), + .s_init_scope = init_scope, +}; diff --git a/asm/include/ivy/asm/assembler.h b/asm/include/ivy/asm/assembler.h index 462d373..28a2125 100644 --- a/asm/include/ivy/asm/assembler.h +++ b/asm/include/ivy/asm/assembler.h @@ -25,6 +25,7 @@ enum ivy_assembler_attrib { IVY_ASM_ATTRIB_GET, IVY_ASM_ATTRIB_SET, IVY_ASM_ATTRIB_PACKAGE, + IVY_ASM_ATTRIB_BLOCK, __IVY_ASM_ATTRIB_COUNT, }; @@ -42,14 +43,14 @@ enum ivy_assembler_xval_type { IVY_ASM_XVAL_NONE = 0, IVY_ASM_XVAL_PROPERTY, IVY_ASM_XVAL_MEMBER_VAR, + IVY_ASM_XVAL_MESSAGE_HANDLER, IVY_ASM_XVAL_PACKAGE_REF, }; enum ivy_assembler_scope_type { IVY_ASM_SCOPE_NONE = 0, IVY_ASM_SCOPE_CLASS, - IVY_ASM_SCOPE_LAMBDA, - IVY_ASM_SCOPE_MSGH, + IVY_ASM_SCOPE_BLOCK, IVY_ASM_SCOPE_CONSTPOOL, IVY_ASM_SCOPE_IMPORT, }; diff --git a/asm/include/ivy/asm/bin.h b/asm/include/ivy/asm/bin.h index 2f05efa..5ca11fa 100644 --- a/asm/include/ivy/asm/bin.h +++ b/asm/include/ivy/asm/bin.h @@ -8,13 +8,13 @@ #define IVY_TABLE_IMPORT 0x58494D50u #define IVY_TABLE_CLASS 0x58434C53u -#define IVY_TABLE_LAMBDA 0x4C424441u -#define IVY_TABLE_MSGH 0x4D534748u #define IVY_TABLE_POOL 0x504F4F4Cu +#define IVY_TABLE_BLOCK 0x54455854u #define IVY_TABLE_XDAT 0x58444154u #define IVY_CLASS_TABLE_MVAR 0x4D564152u #define IVY_CLASS_TABLE_PROP 0x50524F50u +#define IVY_CLASS_TABLE_MSGH 0x4D534748 #define IVY_CONSTPOOL_TABLE_NULL 0x00000000u #define IVY_CONSTPOOL_TABLE_STRING 0x58535452u @@ -49,14 +49,19 @@ struct ivy_bin_class_table_entry { b_i32 p_ident; b_i32 p_get; b_i32 p_set; - b_i32 p_reserved; } e_property; struct { b_i32 m_index; b_i32 m_ident; - uint8_t m_reserved[8]; + uint8_t m_reserved[4]; } e_mvar; + + struct { + b_i32 msg_selector; + b_i32 msg_block; + uint8_t m_reserved[4]; + } e_msgh; }; }; @@ -112,6 +117,10 @@ struct ivy_bin_constpool { struct ivy_bin_constpool_table_entry c_table[]; }; +struct ivy_bin_block { + b_i32 b_index; +}; + struct ivy_bin_import_table_entry { b_i32 e_ident; }; diff --git a/asm/include/ivy/asm/lex.h b/asm/include/ivy/asm/lex.h index fc180d6..4c347c1 100644 --- a/asm/include/ivy/asm/lex.h +++ b/asm/include/ivy/asm/lex.h @@ -32,6 +32,9 @@ enum ivy_asm_keyword { IVY_ASM_KW_CONSTPOOL, IVY_ASM_KW_PACKAGE, IVY_ASM_KW_CLASS, + IVY_ASM_KW_PROPERTY, + IVY_ASM_KW_VAR, + IVY_ASM_KW_MSGH, IVY_ASM_KW_END, __IVY_ASM_KW_INDEX_LIMIT, }; diff --git a/asm/lex.c b/asm/lex.c index a0eac79..ca08f48 100644 --- a/asm/lex.c +++ b/asm/lex.c @@ -29,6 +29,9 @@ static struct lex_token_def keywords[] = { LEX_TOKEN_DEF(IVY_ASM_KW_CLASS, "@class"), LEX_TOKEN_DEF(IVY_ASM_KW_BLOCK, "@block"), LEX_TOKEN_DEF(IVY_ASM_KW_PACKAGE, "@package"), + LEX_TOKEN_DEF(IVY_ASM_KW_PROPERTY, "@property"), + LEX_TOKEN_DEF(IVY_ASM_KW_VAR, "@var"), + LEX_TOKEN_DEF(IVY_ASM_KW_MSGH, "@msgh"), LEX_TOKEN_DEF(IVY_ASM_KW_END, "@end"), }; static const size_t nr_keywords = sizeof keywords / sizeof keywords[0]; @@ -515,7 +518,7 @@ static enum ivy_status push_keyword( static enum ivy_status read_line_comment(struct ivy_asm_lexer *lex) { while (true) { - int c = advance(lex); + int c = peek(lex); if (c == IVY_ERR_EOF || c == '\n') { break; @@ -524,6 +527,8 @@ static enum ivy_status read_line_comment(struct ivy_asm_lexer *lex) if (c < 0) { return c; } + + advance(lex); } return IVY_OK; @@ -1033,6 +1038,9 @@ const char *ivy_asm_keyword_to_string(enum ivy_asm_keyword keyword) ENUM_STR(IVY_ASM_KW_BLOCK); ENUM_STR(IVY_ASM_KW_IMPORT); ENUM_STR(IVY_ASM_KW_PACKAGE); + ENUM_STR(IVY_ASM_KW_PROPERTY); + ENUM_STR(IVY_ASM_KW_VAR); + ENUM_STR(IVY_ASM_KW_MSGH); ENUM_STR(IVY_ASM_KW_END); default: return ""; diff --git a/asm/parse/block.c b/asm/parse/block.c index 139659f..525408b 100644 --- a/asm/parse/block.c +++ b/asm/parse/block.c @@ -18,6 +18,7 @@ enum instr_component { INSTR_NONE = 0, INSTR_OPCODE, + INSTR_OPCODE_DOT, INSTR_OPERAND, INSTR_OPERAND_SEPARATOR, INSTR_OPERAND_INDEX_LEFT, @@ -38,17 +39,25 @@ enum index_base { enum arg_type { ARG_NONE = 0, ARG_CONST, + ARG_LABEL, ARG_REG, ARG_INDEX_REG, ARG_INDEX_CONST, }; +struct label { + b_queue_entry l_entry; + struct ivy_asm_token *l_name; + unsigned long long l_offset; +}; + struct arg { enum arg_type arg_type; b_queue_entry arg_entry; union { struct ivy_asm_token *arg_const; + struct ivy_asm_token *arg_label; struct { struct ivy_asm_token *reg_token; unsigned long long reg_index; @@ -75,7 +84,9 @@ struct block_parser_state { unsigned int s_prev_token; enum instr_component s_prev_component; - struct ivy_asm_token *s_mnemonic; + b_queue s_labels; + + b_queue s_mnemonic; b_queue s_args; struct arg *s_current_arg; @@ -165,6 +176,42 @@ static enum ivy_status push_const_arg( return IVY_OK; } +static enum ivy_status push_label( + struct block_parser_state *state, struct ivy_asm_token *tok) +{ + struct label *label = malloc(sizeof *label); + if (!label) { + return IVY_ERR_NO_MEMORY; + } + + memset(label, 0x0, sizeof *label); + + label->l_name = tok; + /* TODO */ + label->l_offset = 0; + + b_queue_push_back(&state->s_labels, &label->l_entry); + return IVY_OK; +} + +static enum ivy_status push_label_arg( + struct block_parser_state *state, struct ivy_asm_token *tok, + unsigned long long reg_index) +{ + struct arg *arg = malloc(sizeof *arg); + if (!arg) { + return IVY_ERR_NO_MEMORY; + } + + memset(arg, 0x0, sizeof *arg); + + arg->arg_type = ARG_LABEL; + arg->arg_label = tok; + + b_queue_push_back(&state->s_args, &arg->arg_entry); + return IVY_OK; +} + static enum ivy_status push_reg_arg( struct block_parser_state *state, struct ivy_asm_token *tok, unsigned long long reg_index) @@ -235,18 +282,20 @@ static enum ivy_status parse_ident( switch (state->s_prev_component) { case INSTR_NONE: - state->s_mnemonic = tok; + case INSTR_OPCODE_DOT: + b_queue_push_back(&state->s_mnemonic, &tok->t_entry); state->s_prev_component = INSTR_OPCODE; return IVY_OK; case INSTR_OPCODE: case INSTR_OPERAND_SEPARATOR: x = get_register_index(tok); - if (x == REG_INDEX_INVALID) { - return IVY_ERR_BAD_SYNTAX; - } - state->s_prev_component = INSTR_OPERAND; - return push_reg_arg(state, tok, x); + + if (x == REG_INDEX_INVALID) { + return push_label_arg(state, tok, x); + } else { + return push_reg_arg(state, tok, x); + } case INSTR_OPERAND_INDEX_LEFT: x = get_index_base(tok); if (x == INDEX_NONE) { @@ -266,14 +315,32 @@ static enum ivy_status parse_ident( return IVY_ERR_BAD_SYNTAX; } +static enum ivy_status parse_dot( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct block_parser_state *state + = (struct block_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_component != INSTR_OPCODE) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_prev_component = INSTR_OPCODE_DOT; + return IVY_OK; +} + static enum ivy_status parse_label( struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { struct block_parser_state *state = (struct block_parser_state *)asm_parser_get_state(ctx); - /* not sure what this is but we aren't expecting it. */ - return IVY_ERR_BAD_SYNTAX; + if (state->s_prev_component != INSTR_NONE) { + /* not sure what this is but we aren't expecting it. */ + return IVY_ERR_BAD_SYNTAX; + } + + return push_label(state, tok); } static enum ivy_status parse_comma( @@ -355,10 +422,13 @@ static enum ivy_status parse_end( static void init_state(struct ivy_asm_parser *ctx, struct parser_state *state) { + ivy_assembler_begin_scope( + ctx->p_assembler, IVY_ASM_SCOPE_BLOCK, state->s_attrib); } static void finish_state(struct ivy_asm_parser *ctx, struct parser_state *state) { + ivy_assembler_end_scope(ctx->p_assembler); } struct parser_state_type block_parser_state_type = { @@ -375,6 +445,7 @@ struct parser_state_type block_parser_state_type = { SYM_PARSER(LEFT_BRACKET, parse_left_bracket), SYM_PARSER(RIGHT_BRACKET, parse_right_bracket), SYM_PARSER(COMMA, parse_comma), + SYM_PARSER(DOT, parse_dot), }, .n_keyword_parsers = { KW_PARSER(END, parse_end), diff --git a/asm/parse/class.c b/asm/parse/class.c index e69de29..76be265 100644 --- a/asm/parse/class.c +++ b/asm/parse/class.c @@ -0,0 +1,315 @@ +#include "parse.h" + +#include +#include + +enum item_type { + ITEM_NONE = 0, + ITEM_PROPERTY, + ITEM_VAR, + ITEM_MSGH, +}; + +struct class_parser_state { + struct parser_state s_base; + + unsigned int s_prev_token; + enum item_type s_current_item; + ivy_assembler_attrib_table s_current_item_attrib; + + bool s_in_attrib_list; + struct ivy_asm_token *s_attrib_name, *s_attrib_value; +}; + +static enum ivy_status push_attrib(struct class_parser_state *state) +{ + uint64_t hash = b_hash_string(state->s_attrib_name->t_str); + const char *s = state->s_attrib_name->t_str; + unsigned long long v = state->s_attrib_value->t_int.uv; + + switch (hash) { + case HASH_IDENT: + if (!strcmp(s, "ident")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_IDENT] = v; + } + break; + case HASH_INDEX: + if (!strcmp(s, "index")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_INDEX] = v; + } + break; + case HASH_RECIPIENT: + if (!strcmp(s, "recipient")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_RECIPIENT] = v; + } + break; + case HASH_SELECTOR: + if (!strcmp(s, "selector")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_SELECTOR] = v; + } + break; + case HASH_GET: + if (!strcmp(s, "get")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_GET] = v; + } + break; + case HASH_SET: + if (!strcmp(s, "set")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_SET] = v; + } + break; + case HASH_PACKAGE: + if (!strcmp(s, "package")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_PACKAGE] = v; + } + break; + case HASH_BLOCK: + if (!strcmp(s, "block")) { + state->s_current_item_attrib[IVY_ASM_ATTRIB_BLOCK] = v; + } + break; + default: + return IVY_ERR_BAD_SYNTAX; + } + + ivy_asm_token_destroy(state->s_attrib_name); + ivy_asm_token_destroy(state->s_attrib_value); + + state->s_attrib_name = NULL; + state->s_attrib_value = NULL; + + return IVY_OK; +} + +static enum ivy_status parse_property( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_TOK_NONE) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_prev_token = IVY_ASM_TOK_KEYWORD; + state->s_current_item = ITEM_PROPERTY; + memset(state->s_current_item_attrib, 0x0, + sizeof state->s_current_item_attrib); + return IVY_OK; +} + +static enum ivy_status parse_var( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_TOK_NONE) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_prev_token = IVY_ASM_TOK_KEYWORD; + state->s_current_item = ITEM_VAR; + memset(state->s_current_item_attrib, 0x0, + sizeof state->s_current_item_attrib); + return IVY_OK; +} + +static enum ivy_status parse_msgh( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_TOK_NONE) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_prev_token = IVY_ASM_TOK_KEYWORD; + state->s_current_item = ITEM_MSGH; + memset(state->s_current_item_attrib, 0x0, + sizeof state->s_current_item_attrib); + return IVY_OK; +} + +static enum ivy_status parse_left_bracket( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_TOK_KEYWORD) { + return IVY_ERR_BAD_SYNTAX; + } + + if (state->s_in_attrib_list) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_in_attrib_list = true; + state->s_prev_token = IVY_ASM_SYM_LEFT_BRACKET; + + return IVY_OK; +} + +static enum ivy_status parse_right_bracket( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (!state->s_in_attrib_list) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_in_attrib_list = false; + state->s_prev_token = IVY_ASM_SYM_RIGHT_BRACKET; + + return IVY_OK; +} + +static enum ivy_status parse_label( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_SYM_LEFT_BRACKET + && state->s_prev_token != IVY_ASM_TOK_INT) { + return IVY_ERR_BAD_SYNTAX; + } + + if (!state->s_in_attrib_list) { + return IVY_ERR_BAD_SYNTAX; + } + + if (state->s_attrib_name) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_prev_token = IVY_ASM_TOK_LABEL; + state->s_attrib_name = tok; + return IVY_OK; +} + +static enum ivy_status parse_int( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_prev_token != IVY_ASM_TOK_LABEL) { + return IVY_ERR_BAD_SYNTAX; + } + + if (!state->s_in_attrib_list) { + return IVY_ERR_BAD_SYNTAX; + } + + if (state->s_attrib_value) { + return IVY_ERR_BAD_SYNTAX; + } + + state->s_attrib_value = tok; + state->s_prev_token = IVY_ASM_TOK_INT; + return push_attrib(state); +} + +static enum ivy_status parse_linefeed( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_in_attrib_list) { + return IVY_OK; + } + + if (state->s_prev_token != IVY_ASM_TOK_KEYWORD + && state->s_prev_token != IVY_ASM_SYM_RIGHT_BRACKET) { + return IVY_OK; + } + + if (state->s_current_item == 0) { + return IVY_OK; + } + + /* TODO write table entry. */ + switch (state->s_current_item) { + case ITEM_PROPERTY: + ivy_assembler_put_xval( + ctx->p_assembler, IVY_ASM_XVAL_PROPERTY, + state->s_current_item_attrib); + break; + case ITEM_VAR: + ivy_assembler_put_xval( + ctx->p_assembler, IVY_ASM_XVAL_MEMBER_VAR, + state->s_current_item_attrib); + break; + case ITEM_MSGH: + ivy_assembler_put_xval( + ctx->p_assembler, IVY_ASM_XVAL_MESSAGE_HANDLER, + state->s_current_item_attrib); + break; + default: + return IVY_ERR_INTERNAL_FAILURE; + } + + state->s_current_item = 0; + state->s_prev_token = IVY_ASM_TOK_NONE; + + return IVY_OK; +} + +static enum ivy_status parse_end( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) +{ + struct class_parser_state *state + = (struct class_parser_state *)asm_parser_get_state(ctx); + + if (state->s_in_attrib_list) { + return IVY_ERR_BAD_SYNTAX; + } + + switch (state->s_prev_token) { + case IVY_ASM_KW_CLASS: + case IVY_ASM_SYM_RIGHT_BRACKET: + case IVY_ASM_TOK_NONE: + asm_parser_pop_state(ctx, NULL); + return IVY_OK; + default: + return IVY_ERR_BAD_SYNTAX; + } +} + +static void init_state(struct ivy_asm_parser *ctx, struct parser_state *state) +{ + ivy_assembler_begin_scope( + ctx->p_assembler, IVY_ASM_SCOPE_CLASS, state->s_attrib); +} + +static void finish_state(struct ivy_asm_parser *ctx, struct parser_state *state) +{ + ivy_assembler_end_scope(ctx->p_assembler); +} + +struct parser_state_type class_parser_state_type = { + .n_init_state = init_state, + .n_finish_state = finish_state, + .n_state_size = sizeof(struct class_parser_state), + .n_keyword_parsers = { + KW_PARSER(PROPERTY, parse_property), + KW_PARSER(VAR, parse_var), + KW_PARSER(MSGH, parse_msgh), + KW_PARSER(END, parse_end), + }, + .n_symbol_parsers = { + SYM_PARSER(LEFT_BRACKET, parse_left_bracket), + SYM_PARSER(RIGHT_BRACKET, parse_right_bracket), + }, + .n_token_parsers = { + TOK_PARSER(LABEL, parse_label), + TOK_PARSER(INT, parse_int), + TOK_PARSER(LINEFEED, parse_linefeed), + } +}; diff --git a/asm/parse/parse.c b/asm/parse/parse.c index 034469d..9700467 100644 --- a/asm/parse/parse.c +++ b/asm/parse/parse.c @@ -12,6 +12,7 @@ extern struct parser_state_type selector_parser_state_type; extern struct parser_state_type atom_parser_state_type; extern struct parser_state_type import_parser_state_type; extern struct parser_state_type block_parser_state_type; +extern struct parser_state_type class_parser_state_type; static const struct parser_state_type *parser_state_types[] = { [ASM_PARSER_UNIT] = &unit_parser_state_type, @@ -21,6 +22,7 @@ static const struct parser_state_type *parser_state_types[] = { [ASM_PARSER_ATOM] = &atom_parser_state_type, [ASM_PARSER_IMPORT] = &import_parser_state_type, [ASM_PARSER_BLOCK] = &block_parser_state_type, + [ASM_PARSER_CLASS] = &class_parser_state_type, }; static const size_t nr_parser_state_types = sizeof parser_state_types / sizeof parser_state_types[0]; diff --git a/asm/parse/parse.h b/asm/parse/parse.h index 0b28888..37bbe9d 100644 --- a/asm/parse/parse.h +++ b/asm/parse/parse.h @@ -5,6 +5,15 @@ #include #include +#define HASH_IDENT 0x684f633b2528fc75 +#define HASH_INDEX 0x83cf8e8f9081468b +#define HASH_RECIPIENT 0x3d0abea328337078 +#define HASH_SELECTOR 0x03b0355a1af4ac9c +#define HASH_GET 0xd4e26318faaa79f7 +#define HASH_SET 0x823b87195ce20e23 +#define HASH_PACKAGE 0x53cf3eec39cf731b +#define HASH_BLOCK 0x14e5faab9ce0e362 + #define __TOK_PARSER_INDEX(x) ((x) - __IVY_ASM_TOK_INDEX_BASE) #define __SYM_PARSER_INDEX(x) ((x) - __IVY_ASM_SYM_INDEX_BASE) #define __KW_PARSER_INDEX(x) ((x) - __IVY_ASM_KW_INDEX_BASE) diff --git a/asm/parse/unit.c b/asm/parse/unit.c index ecfecf9..980a9dc 100644 --- a/asm/parse/unit.c +++ b/asm/parse/unit.c @@ -1,14 +1,7 @@ #include "parse.h" -#include -#include -#define HASH_IDENT 0x684f633b2528fc75 -#define HASH_INDEX 0x83cf8e8f9081468b -#define HASH_RECIPIENT 0x3d0abea328337078 -#define HASH_SELECTOR 0x03b0355a1af4ac9c -#define HASH_GET 0xd4e26318faaa79f7 -#define HASH_SET 0x823b87195ce20e23 -#define HASH_PACKAGE 0x53cf3eec39cf731b +#include +#include struct unit_parser_state { struct parser_state s_base; @@ -63,6 +56,11 @@ static enum ivy_status push_attrib(struct unit_parser_state *state) state->s_next_scope_attrib[IVY_ASM_ATTRIB_PACKAGE] = v; } break; + case HASH_BLOCK: + if (!strcmp(s, "block")) { + state->s_next_scope_attrib[IVY_ASM_ATTRIB_BLOCK] = v; + } + break; default: return IVY_ERR_BAD_SYNTAX; } @@ -76,9 +74,11 @@ static enum ivy_status push_attrib(struct unit_parser_state *state) return IVY_OK; } -static enum ivy_status parse_constpool(struct ivy_asm_parser* ctx, struct ivy_asm_token* tok) +static enum ivy_status parse_constpool( + struct ivy_asm_parser *ctx, struct ivy_asm_token *tok) { - struct unit_parser_state *state = (struct unit_parser_state *)asm_parser_get_state(ctx); + struct unit_parser_state *state + = (struct unit_parser_state *)asm_parser_get_state(ctx); if (state->s_prev_token != IVY_ASM_TOK_NONE) { return IVY_ERR_BAD_SYNTAX; @@ -180,7 +180,8 @@ static enum ivy_status parse_label( struct unit_parser_state *state = (struct unit_parser_state *)asm_parser_get_state(ctx); - if (state->s_prev_token != IVY_ASM_SYM_LEFT_BRACKET && state->s_prev_token != IVY_ASM_TOK_INT) { + if (state->s_prev_token != IVY_ASM_SYM_LEFT_BRACKET + && state->s_prev_token != IVY_ASM_TOK_INT) { return IVY_ERR_BAD_SYNTAX; } @@ -230,7 +231,8 @@ static enum ivy_status parse_linefeed( return IVY_OK; } - if (state->s_prev_token != IVY_ASM_TOK_KEYWORD && state->s_prev_token != IVY_ASM_SYM_RIGHT_BRACKET) { + if (state->s_prev_token != IVY_ASM_TOK_KEYWORD + && state->s_prev_token != IVY_ASM_SYM_RIGHT_BRACKET) { return IVY_OK; } @@ -262,4 +264,4 @@ struct parser_state_type unit_parser_state_type = { TOK_PARSER(INT, parse_int), TOK_PARSER(LINEFEED, parse_linefeed), } -}; \ No newline at end of file +};