mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-11 00:38:18 +03:00
jaf: messages and char constants
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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*));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
int main()
|
||||
{
|
||||
array@int@2 a[1][2];
|
||||
a[0][1] = 1;
|
||||
return !(a[0][1] == 1);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
int main()
|
||||
{
|
||||
return !('a' == 97);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
int result = 0;
|
||||
|
||||
void message(int n, int total, string msg)
|
||||
{
|
||||
result = msg == "test";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
'test';
|
||||
return !(result == 1);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user