jaf: messages and char constants

This commit is contained in:
Nunuhara Cabbage
2020-07-05 22:29:45 -07:00
parent 8fe1001fc3
commit d3928c774d
16 changed files with 180 additions and 4 deletions
+1
View File
@@ -343,6 +343,7 @@ int ain_add_function(struct ain *ain, struct ain_function *fun);
int ain_add_functype(struct ain *ain, struct ain_function_type *fun);
int ain_get_functype(struct ain *ain, const char *name);
int ain_add_string(struct ain *ain, const char *str);
int ain_add_message(struct ain *ain, const char *str);
int ain_add_file(struct ain *ain, const char *filename);
void ain_free(struct ain *ain);
+7
View File
@@ -311,6 +311,13 @@ int ain_add_string(struct ain *ain, const char *str)
return i;
}
int ain_add_message(struct ain *ain, const char *str)
{
ain->messages = xrealloc_array(ain->messages, ain->nr_messages, ain->nr_messages+1, sizeof(struct string*));
ain->messages[ain->nr_messages++] = make_string(str, strlen(str));
return ain->nr_messages - 1;
}
int ain_add_file(struct ain *ain, const char *filename)
{
ain->filenames = xrealloc_array(ain->filenames, ain->nr_filenames, ain->nr_filenames+1, sizeof(char*));
+9
View File
@@ -56,6 +56,7 @@ enum jaf_expression_type {
JAF_EXP_MEMBER,
JAF_EXP_SEQ,
JAF_EXP_SUBSCRIPT,
JAF_EXP_CHAR,
};
enum jaf_operator {
@@ -211,6 +212,7 @@ enum block_item_kind {
JAF_STMT_RETURN,
JAF_STMT_CASE,
JAF_STMT_DEFAULT,
JAF_STMT_MESSAGE,
JAF_EOF
};
@@ -266,6 +268,11 @@ struct jaf_block_item {
struct jaf_expression *after;
struct jaf_block_item *body;
} for_loop;
struct {
struct string *text;
struct string *func;
int func_no;
} msg;
struct string *target; // goto
unsigned file_no; // eof
};
@@ -291,6 +298,7 @@ struct jaf_expression *jaf_float(float f);
struct jaf_expression *jaf_parse_float(struct string *text);
struct string *jaf_process_string(struct string *text);
struct jaf_expression *jaf_string(struct string *text);
struct jaf_expression *jaf_char(struct string *text);
struct jaf_expression *jaf_identifier(struct string *name);
struct jaf_expression *jaf_unary_expr(enum jaf_operator op, struct jaf_expression *expr);
struct jaf_expression *jaf_binary_expr(enum jaf_operator op, struct jaf_expression *lhs, struct jaf_expression *rhs);
@@ -339,6 +347,7 @@ struct jaf_block_item *jaf_goto(struct string *target);
struct jaf_block_item *jaf_continue(void);
struct jaf_block_item *jaf_break(void);
struct jaf_block_item *jaf_return(struct jaf_expression *expr);
struct jaf_block_item *jaf_message_statement(struct string *msg, struct string *func);
void jaf_free_expr(struct jaf_expression *expr);
void jaf_free_block(struct jaf_block *block);
+29
View File
@@ -104,6 +104,14 @@ struct jaf_expression *jaf_string(struct string *text)
return e;
}
struct jaf_expression *jaf_char(struct string *text)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_CHAR, 0);
e->valuetype.data = AIN_INT;
e->s = text;
return e;
}
struct jaf_expression *jaf_identifier(struct string *name)
{
struct jaf_expression *e = jaf_expr(JAF_EXP_IDENTIFIER, 0);
@@ -445,8 +453,23 @@ struct jaf_block_item *jaf_case_statement(struct jaf_expression *expr, struct ja
return item;
}
struct jaf_block_item *jaf_message_statement(struct string *msg, struct string *func)
{
struct jaf_block_item *item = block_item(JAF_STMT_MESSAGE);
item->msg.text = msg;
item->msg.func = func;
return item;
}
struct jaf_block_item *jaf_expression_statement(struct jaf_expression *expr)
{
// NOTE: character constant as statement is treated as a message
if (expr->type == JAF_EXP_CHAR) {
struct string *s = expr->s;
free(expr);
return jaf_message_statement(s, NULL);
}
struct jaf_block_item *item = block_item(JAF_STMT_EXPRESSION);
item->expr = expr;
return item;
@@ -531,6 +554,7 @@ void jaf_free_expr(struct jaf_expression *expr)
case JAF_EXP_FLOAT:
break;
case JAF_EXP_STRING:
case JAF_EXP_CHAR:
case JAF_EXP_IDENTIFIER:
free_string(expr->s);
break;
@@ -659,6 +683,11 @@ void jaf_free_block_item(struct jaf_block_item *item)
jaf_free_expr(item->swi_case.expr);
jaf_free_block_item(item->swi_case.stmt);
break;
case JAF_STMT_MESSAGE:
free_string(item->msg.text);
if (item->msg.func)
free_string(item->msg.func);
break;
}
free(item);
}
+14
View File
@@ -617,6 +617,9 @@ static void compile_expression(struct compiler_state *state, struct jaf_expressi
case JAF_EXP_SUBSCRIPT:
compile_subscript(state, expr);
break;
case JAF_EXP_CHAR:
ERROR("Unresolved character constant"); // should have been simplified to int
break;
}
}
@@ -887,6 +890,14 @@ static void compile_break(struct compiler_state *state)
write_instruction1(state, JUMP, 0);
}
static void compile_message(struct compiler_state *state, struct jaf_block_item *item)
{
int no = ain_add_message(state->ain, item->msg.text->text);
write_instruction1(state, MSG, no);
if (item->msg.func)
write_instruction1(state, CALLFUNC, item->msg.func_no);
}
static void compile_statement(struct compiler_state *state, struct jaf_block_item *item)
{
switch (item->kind) {
@@ -942,6 +953,9 @@ static void compile_statement(struct compiler_state *state, struct jaf_block_ite
case JAF_STMT_DEFAULT:
ERROR("switch not supported");
break;
case JAF_STMT_MESSAGE:
compile_message(state, item);
break;
case JAF_EOF:
write_instruction1(state, _EOF, item->file_no);
break;
+30
View File
@@ -341,6 +341,34 @@ static struct jaf_expression *jaf_simplify_subscript(struct jaf_expression *in)
return in;
}
static struct jaf_expression *jaf_simplify_char(struct jaf_expression *in)
{
int c = 0;
int size = in->s->size;
char *s = in->s->text;
if (size <= 0)
goto invalid;
if (s[0] == '\\') {
if (size != 2)
goto invalid;
switch (s[1]) {
case '\\': c = '\\'; goto valid;
case '\'': c = '\''; goto valid;
default: goto invalid;
}
}
if (size != 1)
goto invalid;
c = s[0];
valid:
free_string(in->s);
in->type = JAF_EXP_INT;
in->i = c;
return in;
invalid:
ERROR("Invalid character constant");
}
/*
* Simplify an expression by evaluating the constant parts.
*/
@@ -370,6 +398,8 @@ struct jaf_expression *jaf_simplify(struct jaf_expression *in)
return jaf_simplify_seq(in);
case JAF_EXP_SUBSCRIPT:
return jaf_simplify_subscript(in);
case JAF_EXP_CHAR:
return jaf_simplify_char(in);
}
ERROR("Invalid expression type");
}
+1 -1
View File
@@ -97,7 +97,7 @@ unsigned long jaf_line = 1;
{HP}{H}+{IS}? { RETURN_STRING(I_CONSTANT); }
{NZ}{D}*{IS}? { RETURN_STRING(I_CONSTANT); }
"0"{O}*{IS}? { RETURN_STRING(I_CONSTANT); }
"'"([^'\\\n]|{ES})+"'" { RETURN_STRING(I_CONSTANT); }
"'"([^'\\\n]|{ES})+"'" { yylval.string = make_string(yytext+1, yyleng-2); return C_CONSTANT; }
{D}+{E}{FS}? { RETURN_STRING(F_CONSTANT); }
{D}*"."{D}+{E}?{FS}? { RETURN_STRING(F_CONSTANT); }
+8 -3
View File
@@ -155,7 +155,7 @@ static struct string *time_macro(void)
struct jaf_function_declarator *fundecl;
}
%token <string> I_CONSTANT F_CONSTANT STRING_LITERAL
%token <string> I_CONSTANT F_CONSTANT C_CONSTANT STRING_LITERAL
%token <string> IDENTIFIER TYPEDEF_NAME ENUMERATION_CONSTANT
%token <token> INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
@@ -191,7 +191,7 @@ static struct string *time_macro(void)
%type <block> functype_parameter_list functype_parameter_declaration
%type <block> compound_statement block_item_list block_item
%type <statement> statement labeled_statement expression_statement selection_statement
%type <statement> iteration_statement jump_statement
%type <statement> iteration_statement jump_statement message_statement
%type <fundecl> function_declarator functype_declarator
/*
@@ -200,7 +200,6 @@ static struct string *time_macro(void)
* 2. functype vs global
*/
%expect 1
%precedence FUNCTYPE
%start toplevel
%%
@@ -214,6 +213,7 @@ primary_expression
constant
: I_CONSTANT { $$ = jaf_parse_integer($1); } /* includes character_constant */
| C_CONSTANT { $$ = jaf_char($1); }
| F_CONSTANT { $$ = jaf_parse_float($1); }
| ENUMERATION_CONSTANT { ERROR("Enums not supported"); } /* after it has been defined as such */
;
@@ -499,6 +499,7 @@ statement
| selection_statement { $$ = $1; }
| iteration_statement { $$ = $1; }
| jump_statement { $$ = $1; }
| message_statement { $$ = $1; }
;
labeled_statement
@@ -550,6 +551,10 @@ jump_statement
| SYM_RETURN expression ';' { $$ = jaf_return($2); }
;
message_statement
: C_CONSTANT IDENTIFIER ';' { $$ = jaf_message_statement($1, $2); }
;
toplevel
: translation_unit { jaf_toplevel = jaf_merge_blocks(jaf_toplevel, $1); }
;
+32
View File
@@ -241,6 +241,19 @@ static void analyze_function(struct jaf_env *env, struct jaf_declaration *decl)
free(funenv);
}
static void analyze_message(struct jaf_env *env, struct jaf_block_item *item)
{
if (!item->msg.func) {
item->msg.func_no = -1;
return;
}
char *u = encode_text_to_input_format(item->msg.func->text);
if ((item->msg.func_no = ain_get_function_no(env->ain, u)) < 0)
ERROR("Undefined function: %s", item->msg.func->text);
free(u);
}
static struct jaf_env *push_env(struct jaf_env *parent)
{
struct jaf_env *newenv = xcalloc(1, sizeof(struct jaf_env));
@@ -313,6 +326,8 @@ static void analyze_statement(struct jaf_env *env, struct jaf_block_item *item)
case JAF_STMT_DEFAULT:
analyze_statement(env, item->swi_case.stmt);
break;
case JAF_STMT_MESSAGE:
analyze_message(env, item);
case JAF_FUNCTYPE_DECL:
case JAF_STMT_GOTO:
case JAF_STMT_CONTINUE:
@@ -408,6 +423,7 @@ static void resolve_statement_types(struct ain *ain, struct jaf_block_item *item
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_STMT_RETURN:
case JAF_STMT_MESSAGE:
case JAF_EOF:
break;
}
@@ -492,6 +508,7 @@ static struct ain_variable *block_item_get_vars(struct ain *ain, struct jaf_bloc
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_STMT_RETURN:
case JAF_STMT_MESSAGE:
case JAF_EOF:
break;
@@ -539,6 +556,21 @@ static void add_function(struct ain *ain, struct jaf_declaration *decl)
if (ain->main > 0)
WARNING("Overriding main function");
ain->main = decl->func_no;
} else if (!strcmp(decl->name->text, "message")) {
if (!decl->params ||
decl->params->nr_items != 3 ||
decl->params->items[0]->decl.type->type != JAF_INT ||
decl->params->items[0]->decl.type->qualifiers ||
decl->params->items[1]->decl.type->type != JAF_INT ||
decl->params->items[1]->decl.type->qualifiers ||
decl->params->items[2]->decl.type->type != JAF_STRING ||
decl->params->items[2]->decl.type->qualifiers ||
decl->type->type != JAF_VOID) {
ERROR("Invalid signature for message function");
}
if (ain->msgf > 0)
WARNING("Overriding message function");
ain->msgf = decl->func_no;
}
}
+1
View File
@@ -540,6 +540,7 @@ void jaf_derive_types(struct jaf_env *env, struct jaf_expression *expr)
expr->valuetype.data = AIN_VOID;
break;
case JAF_EXP_INT:
case JAF_EXP_CHAR:
expr->valuetype.data = AIN_INT;
break;
case JAF_EXP_FLOAT:
+6
View File
@@ -0,0 +1,6 @@
int main()
{
array@int@2 a[1][2];
a[0][1] = 1;
return !(a[0][1] == 1);
}
+4
View File
@@ -0,0 +1,4 @@
int main()
{
return !('a' == 97);
}
+16
View File
@@ -0,0 +1,16 @@
int result = 0;
void message(int n, int total, string msg)
{
}
void A(void)
{
result = 1;
}
int main()
{
'test' A;
return !(result == 1);
}
+12
View File
@@ -0,0 +1,12 @@
int result = 0;
void message(int n, int total, string msg)
{
result = msg == "test";
}
int main()
{
'test';
return !(result == 1);
}
+5
View File
@@ -103,3 +103,8 @@ cd $(dirname "$0")
./test-runner.sh functype.jaf
./test-runner.sh functype-void.jaf
./test-runner.sh functype-ref-int.jaf
./test-runner.sh message.jaf
./test-runner.sh message-call.jaf
./test-runner.sh char-constant.jaf
@@ -0,0 +1,5 @@
int main()
{
string a = "asdf\n" "\nfdsa";
return !(a == "asdf\n\nfdsa");
}