interim update

This commit is contained in:
hyunghwan.chung 2015-06-03 04:22:19 +00:00
parent 03aab810b9
commit e6137a5864
4 changed files with 306 additions and 259 deletions

View File

@ -68,9 +68,10 @@ enum mth_type_t
MTH_CLASS MTH_CLASS
}; };
/* NOTE store_opcodes table depends on the order of var_tsype_t */
enum var_type_t enum var_type_t
{ {
VAR_ARGUMENT,
VAR_TEMPORARY,
VAR_INSTANCE, VAR_INSTANCE,
VAR_CLASS, VAR_CLASS,
VAR_CLASSINST VAR_CLASSINST
@ -1016,95 +1017,32 @@ static int end_include (stix_t* stix)
} }
#if 0
/* ---------------------------------------------------------------------
* Parser and Code Generator
* --------------------------------------------------------------------- */
#define EMIT_CODE_TEST(fsc,high,low) \
do { if (emit_code_test(fsc,high,low) <= -1) return -1; } while (0)
#define EMIT_PUSH_RECEIVER_VARIABLE(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, PUSH_RECEIVER_VARIABLE, pos) <= -1) return -1; \
} while (0)
#define EMIT_PUSH_TEMPORARY_LOCATION(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, PUSH_TEMPORARY_LOCATION, pos) <= -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_CONSTANT(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, PUSH_LITERAL_CONSTANT, pos) <= -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_VARIABLE(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, PUSH_LITERAL_VARIABLE, pos) <= -1) return -1; \
} while (0)
#define EMIT_STORE_RECEIVER_VARIABLE(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, STORE_RECEIVER_VARIABLE, pos) <= -1) return -1; \
} while (0)
#define EMIT_STORE_TEMPORARY_LOCATION(fsc,pos) \
do { \
if (emit_stack_positional ( \
fsc, STORE_TEMPORARY_LOCATION, pos) <= -1) return -1; \
} while (0)
#define EMIT_POP_STACK_TOP(fsc) EMIT_CODE(fsc, POP_STACK_TOP)
#define EMIT_DUPLICATE_STACK_TOP(fsc) EMIT_CODE(fsc, DUPLICATE_STACK_TOP)
#define EMIT_PUSH_ACTIVE_CONTEXT(fsc) EMIT_CODE(fsc, PUSH_ACTIVE_CONTEXT)
#define EMIT_RETURN_FROM_MESSAGE(fsc) EMIT_CODE(fsc, RETURN_FROM_MESSAGE)
#define EMIT_RETURN_FROM_BLOCK(fsc) EMIT_CODE(fsc, RETURN_FROM_BLOCK)
#define EMIT_SEND_TO_SELF(fsc,nargs,selector) \
do { \
if (emit_send_to_self(fsc,nargs,selector) <= -1) return -1; \
} while (0)
#define EMIT_SEND_TO_SUPER(fsc,nargs,selector) \
do { \
if (emit_send_to_super(fsc,nargs,selector) <= -1) return -1; \
} while (0)
#define EMIT_DO_PRIMITIVE(fsc,no) \
do { if (emit_do_primitive(fsc,no) <= -1) return -1; } while(0)
#endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
#define CODE_MAKE(x,y) (((x) << 4) | y) #define MAKE_CODE(x,y) (((x) << 4) | y)
#define CODE_MAX_INDEX 0xFFFF #define MAX_CODE_INDEX 0xFFFF
#define CODE_EXTEND 0x0 #define CMD_EXTEND 0x0
#define CODE_EXTEND_DOUBLE 0x1 #define CMD_EXTEND_DOUBLE 0x1
#define CODE_STORE_INTO_INSTVAR 0x7 /* pop and store */ #define CMD_PUSH_INSTVAR 0x2
#define CODE_STORE_INTO_CLASSSIDEVAR 0x8 /* pop and store */ #define CMD_PUSH_TEMPVAR 0x3
#define CODE_STORE_INTO_TEMPVAR 0x9 /* pop and store */ #define CMD_STORE_INTO_INSTVAR 0x7 /* pop and store */
#define CODE_SPECIAL 0xF #define CMD_STORE_INTO_CLASSVAR 0x8 /* pop and store */
#define CMD_STORE_INTO_TEMPVAR 0x9 /* pop and store */
/* ---------------------------------- */
#define CODE_PUSH_NIL 0x61
#define CODE_PUSH_TRUE 0x62
#define CODE_PUSH_FALSE 0x63
/* special code */ /* special code */
#define CODE_DUP_STACKTOP 0x1 #define CODE_DUP_STACKTOP 0xF1
#define CODE_POP_STACKTOp 0x2 #define CODE_POP_STACKTOP 0xF2
#define CODE_RETURN_MESSAGE_STACKTOP 0x3 #define CODE_RETURN_MESSAGE_STACKTOP 0xF3
#define CODE_RETURN_BLOCK_STACKTOP 0x4 #define CODE_RETURN_BLOCK_STACKTOP 0xF4
#define CODE_RETURN_MESSAGE_RECEIVER 0x5 #define CODE_RETURN_MESSAGE_RECEIVER 0xF5
#define CODE_EXEC_PRIMITIVE 0xF #define CODE_EXEC_PRIMITIVE 0xFF
static STIX_INLINE int emit_code (stix_t* stix, stix_byte_t code) static STIX_INLINE int emit_code (stix_t* stix, stix_byte_t code)
{ {
@ -1128,24 +1066,24 @@ static STIX_INLINE int emit_code (stix_t* stix, stix_byte_t code)
return 0; return 0;
} }
static int emit_pop_and_store (stix_t* stix, stix_size_t index, int store_code) static int emit_pop_and_store (stix_t* stix, stix_size_t index, int store_cmd)
{ {
STIX_ASSERT (index <= CODE_MAX_INDEX); STIX_ASSERT (index <= MAX_CODE_INDEX);
if (index > 0xFF) if (index > 0xFF)
{ {
if (emit_code(stix, CODE_MAKE(CODE_EXTEND_DOUBLE, store_code)) <= -1 || if (emit_code(stix, MAKE_CODE(CMD_EXTEND_DOUBLE, store_cmd)) <= -1 ||
emit_code(stix, index >> 8) <= -1 || emit_code(stix, index >> 8) <= -1 ||
emit_code(stix, index & 0xFF) <= -1) return -1; emit_code(stix, index & 0xFF) <= -1) return -1;
} }
else if (index > 0xF) else if (index > 0xF)
{ {
if (emit_code(stix, CODE_MAKE(CODE_EXTEND, store_code)) <= -1 || if (emit_code(stix, MAKE_CODE(CMD_EXTEND, store_cmd)) <= -1 ||
emit_code(stix, index) <= -1) return -1; emit_code(stix, index) <= -1) return -1;
} }
else else
{ {
if (emit_code(stix, CODE_MAKE(store_code, index)) <= -1) return -1; if (emit_code(stix, MAKE_CODE(store_cmd, index)) <= -1) return -1;
} }
return 0; return 0;
@ -1393,66 +1331,6 @@ static int parse_block_statements (stix_t* fsc)
} }
static int parse_basic_expression (stix_t* fsc, const stix_uch_t* ident)
{
/*
* <basic expression> := <primary> [<messages> <cascaded messages>]
*/
int is_super;
if (parse_primary(fsc, ident, &is_super) == -1) return -1;
if (fsc->tok.type != STIX_IOTOK_EOF &&
fsc->tok.type != STIX_IOTOK_RBRACE &&
fsc->tok.type != STIX_IOTOK_PERIOD)
{
if (parse_message_continuation(fsc, is_super) == -1) return -1;
}
return 0;
}
static int parse_assignment (stix_t* fsc, const stix_uch_t* target)
{
/*
* <assignment> := <assignment target> assignmentOperator <expression>
*/
stix_word_t i;
stix_vm_t* stx = fsc->stx;
for (i = fsc->met.tmpr.nargs; i < fsc->met.tmpr.count; i++)
{
if (stix_strequal (target, fsc->met.tmpr.names[i]))
{
if (parse_expression(fsc) == -1) return -1;
EMIT_STORE_TEMPORARY_LOCATION (fsc, i);
return 0;
}
}
if (stix_get_instance_variable_index (stx, fsc->method_class, target, &i) == 0)
{
if (parse_expression(fsc) == -1) return -1;
EMIT_STORE_RECEIVER_VARIABLE (fsc, i);
return 0;
}
if (stix_lookup_class_variable (stx, fsc->method_class, target) != stx->nil)
{
if (parse_expression(fsc) == -1) return -1;
/* TODO */
EMIT_CODE_TEST (fsc, STIX_T("ASSIGN_CLASSVAR #"), target);
//EMIT_STORE_CLASS_VARIABLE (fsc, target);
return 0;
}
/* TODO: IMPLEMENT POOL DICTIONARIES */
/* TODO: IMPLEMENT GLOBLAS, but i don't like this idea */
fsc->errnum = STIX_FSC_ERROR_UNDECLARED_NAME;
return -1;
}
static int parse_primary (stix_t* fsc, const stix_uch_t* ident, int* is_super) static int parse_primary (stix_t* fsc, const stix_uch_t* ident, int* is_super)
{ {
@ -1814,8 +1692,7 @@ static int parse_unary_message (stix_t* fsc, int is_super)
while (fsc->tok.type == STIX_IOTOK_IDENT) while (fsc->tok.type == STIX_IOTOK_IDENT)
{ {
pos = __add_symbol_literal (fsc, pos = __add_symbol_literal (fsc, fsc->tok.name.buffer, fsc->tok.name.size);
fsc->tok.name.buffer, fsc->tok.name.size);
if (pos == -1) return -1; if (pos == -1) return -1;
n = (is_super)? emit_send_to_super (fsc, 0, pos): n = (is_super)? emit_send_to_super (fsc, 0, pos):
@ -2251,6 +2128,8 @@ static int compile_method_primitive (stix_t* stix)
/* /*
* method-primitive := "<" "primitive:" integer ">" * method-primitive := "<" "primitive:" integer ">"
*/ */
int prim_no;
const stix_uch_t* ptr, * end;
if (!is_token_binsel(stix, KSYM_LT)) if (!is_token_binsel(stix, KSYM_LT))
{ {
@ -2276,23 +2155,24 @@ static int compile_method_primitive (stix_t* stix)
return -1; return -1;
} }
/*TODO: more checks the validity of the primitive number */ /*TODO: more checks the validity of the primitive number. support nubmer with radix and so on support more extensive syntax */
#if 0 ptr = stix->c->tok.name.ptr;
if (!stix_stristype(stix->tok.name.buffer, stix_isdigit)) end = ptr + stix->c->tok.name.len;
prim_no = 0;
while (ptr < end && is_digitchar(*ptr))
{ {
stix->errnum = STIX_FSC_ERROR_PRIMITIVE_NUMBER; prim_no = prim_no * 10 + (*ptr - '0');
return -1; if (prim_no > 0xFF)
{
set_syntax_error (stix, STIX_SYNERR_PRIMITIVENO, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
ptr++;
} }
STIX_STRTOI (stix->c->mth.prim_no, stix->tok.name.buffer, STIX_NULL, 10); if (emit_code(stix, CODE_EXEC_PRIMITIVE) <= -1 ||
if (prim_no < 0 || prim_no > 0xFF) emit_code(stix, prim_no) <= -1) return -1;
{
stix->errnum = STIX_FSC_ERROR_PRIMITIVE_NUMBER_RANGE;
return -1;
}
EMIT_DO_PRIMITIVE (stix, stix-.c->fun.prim_no);
#endif
GET_TOKEN (stix); GET_TOKEN (stix);
if (!is_token_binsel(stix, KSYM_GT)) if (!is_token_binsel(stix, KSYM_GT))
@ -2305,32 +2185,91 @@ static int compile_method_primitive (stix_t* stix)
return 0; return 0;
} }
static int compile_method_expression (stix_t* stix);
static int get_variable_info (stix_t* stix, const stix_ucs_t* name, const stix_ioloc_t* name_loc, var_info_t* var)
static int compile_basic_expression (stix_t* stix, const stix_ucs_t* assignee)
{ {
#if 0 stix_ssize_t index;
/*
* <basic expression> := <primary> [<messages> <cascaded messages>]
*/
int is_super;
if (parse_primary(stix, ident, &is_super) == -1) return -1; index = find_temporary_variable (stix, name);
if (stix->tok.type != STIX_IOTOK_EOF && if (index >= 0)
stix->tok.type != STIX_IOTOK_RBRACE &&
stix->tok.type != STIX_IOTOK_PERIOD)
{ {
if (parse_message_continuation(stix, is_super) == -1) return -1; STIX_MEMSET (&var, 0, STIX_SIZEOF(var));
if (index < stix->c->mth.tmpr_nargs)
{
var->type = VAR_ARGUMENT;
}
else
{
var->type = VAR_TEMPORARY;
}
var->pos = index;
} }
else
{
if (find_class_level_variable(stix, stix->c->cls.self_oop, name, var) >= 0)
{
switch (var->type)
{
case VAR_INSTANCE:
if (stix->c->mth.type == MTH_CLASS)
{
/* a class method cannot access an instance variable */
set_syntax_error (stix, STIX_SYNERR_VARINACC, name_loc, name);
return -1;
}
break;
case VAR_CLASS:
/* TODO: change code here ... */
/* a class variable can be access by both instance methods and class methods */
STIX_ASSERT (var->cls != STIX_NULL);
STIX_ASSERT (STIX_CLASSOF(stix, var->cls) == stix->_class);
/* TOOD: index must be incremented witht eh number of classinstancevariables counts from var.cls
* verify if the below increment is correct*/
var->pos += STIX_CLASS_SELFSPEC_CLASSINSTVAR(STIX_OOP_TO_SMINT(var->cls->selfspec));
break;
case VAR_CLASSINST:
/* class instance variable can be accessed by only class methods */
if (stix->c->mth.type == MTH_INSTANCE)
{
/* an instance method cannot access a class-instance variable */
set_syntax_error (stix, STIX_SYNERR_VARINACC, name_loc, name);
return -1;
}
/* to a class object itself, a class-instance variable is
* just an instance variriable */
break;
default:
/* internal error - it must not happen */
stix->errnum = STIX_EINTERN;
return -1;
}
}
else
{
/* undeclared identifier */
set_syntax_error (stix, STIX_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
}
if (index > MAX_CODE_INDEX)
{
/* the assignee is not usable because its index is too large
* to be expressed in byte-codes. */
set_syntax_error (stix, STIX_SYNERR_VARUNUSE, name_loc, name);
return -1;
}
return 0; return 0;
#endif
return -1;
} }
static int compile_method_expression (stix_t* stix);
static int compile_assignment_expression (stix_t* stix, const stix_ucs_t* assignee, const stix_ioloc_t* assignee_loc) static int compile_assignment_expression (stix_t* stix, const stix_ucs_t* assignee, const stix_ioloc_t* assignee_loc)
{ {
@ -2338,102 +2277,201 @@ static int compile_assignment_expression (stix_t* stix, const stix_ucs_t* assign
* assignment-expression := identifier ":=" method-expression * assignment-expression := identifier ":=" method-expression
*/ */
stix_ssize_t index;
var_info_t var; var_info_t var;
printf ("ASSIGNIUNG TO ...."); printf ("ASSIGNIUNG TO ....");
print_ucs (assignee); print_ucs (assignee);
printf ("\n"); printf ("\n");
index = find_temporary_variable (stix, assignee); if (get_variable_info (stix, assignee, assignee_loc, &var) <= -1) return -1;
if (index >= 0)
switch (var.type)
{ {
if (index < stix->c->mth.tmpr_nargs) case VAR_ARGUMENT:
{
/* assigning to an argument is not allowed */ /* assigning to an argument is not allowed */
set_syntax_error (stix, STIX_SYNERR_ASSIGNEEARG, assignee_loc, assignee); set_syntax_error (stix, STIX_SYNERR_VARARG, assignee_loc, assignee);
return -1; return -1;
}
/* assigning to a temporary variable */
if (compile_method_expression(stix) <= -1) return -1;
if (index > CODE_MAX_INDEX) case VAR_TEMPORARY:
{ return emit_pop_and_store (stix, var.pos, CMD_STORE_INTO_TEMPVAR);
set_syntax_error (stix, STIX_SYNERR_ASSIGNEEUNEXP, assignee_loc, assignee);
case VAR_INSTANCE:
case VAR_CLASSINST:
return emit_pop_and_store (stix, var.pos, CMD_STORE_INTO_INSTVAR);
case VAR_CLASS:
/* TODO: what instruction to generate for class variable access... */
return -1; return -1;
}
return emit_pop_and_store (stix, index, CODE_STORE_INTO_TEMPVAR);
default:
stix->errnum = STIX_EINTERN;
return -1;
} }
else if (find_class_level_variable(stix, stix->c->cls.self_oop, assignee, &var) >= 0) }
static int compile_expression_primary (stix_t* stix, const stix_ucs_t* ident, const stix_ioloc_t* ident_loc)
{
/*
* expression-primary := identifier | literal | block-constructor | ( "(" method-expression ")" )
*/
var_info_t var;
if (ident)
{ {
/* THIS TABLE MUST MATCH var_type_t */ handle_ident:
static stix_byte_t store_opcodes[] = /*if (parse_primary_ident(stix, stix->tok.name.buffer) == -1) return -1;*/
{ if (compile_primary_ident(stix, ident, ident_loc) <= -1) return -1;
CODE_STORE_INTO_INSTVAR,
CODE_STORE_INTO_CLASSSIDEVAR,
CODE_STORE_INTO_CLASSSIDEVAR
};
/* --------------------------------- */
stix_size_t index; if (get_variable_info (stix, ident, ident_loc, &var) <= -1) return -1;
}
else
{
/*stix_size_t index;*/
index = var.pos; switch (stix->c->tok.type)
if (var.type != VAR_INSTANCE)
{ {
STIX_ASSERT (var.type == VAR_CLASS || var.type == VAR_CLASSINST); case STIX_IOTOK_IDENT:
/* TODO: calculate the right position/index */ ident = &stix->c->tok.name;
ident_loc = &stix->c->tok.loc;
goto handle_ident;
if (compile_variable_push(stix, &stix->c->tok.name, &stix->c->tok.loc) <= -1) return -1;
GET_TOKEN (stix);
break;
case STIX_IOTOK_SELF:
/* TODO: */
break;
case STIX_IOTOK_SUPER:
/* TODO: */
break;
case STIX_IOTOK_NIL:
if (emit_code(stix, CODE_PUSH_NIL) <= -1) return -1;
break;
case STIX_IOTOK_TRUE:
if (emit_code(stix, CODE_PUSH_TRUE) <= -1) return -1;
break;
case STIX_IOTOK_FALSE:
if (emit_code(stix, CODE_PUSH_FALSE) <= -1) return -1;
break;
case STIX_IOTOK_THIS_CONTEXT:
/* TODO */
break;
case STIX_IOTOK_CHRLIT:
/*
STIX_ASSERT (stix->c->tok.name.len == 1);
if (add_character_literal(stix, stix->c->tok.name[0], &index) <= -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (stix, index);
GET_TOKEN (stix);
*/
break;
case STIX_IOTOK_STRLIT:
/*
if (add_string_literal(stix, stix->c->tok.name, &index) <= -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (stix, index);
GET_TOKEN (stix);
*/
break;
case STIX_IOTOK_SYMLIT:
/*
if (add_symbol_literal(stix, stix->c->tok.name, &index) <= -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (stix, index);
GET_TOKEN (stix);
*/
break;
case STIX_IOTOK_NUMLIT:
{
/* TODO: other types of numbers, negative numbers, etc */
/*
stix_word_t tmp;
STIX_STRTOI (tmp, stix->tok.name.buffer, STIX_NULL, 10);
literal = STIX_TO_SMALLINT(tmp);
if (add_literal(stix, literal, &index) <= -1)r eturn -1;
EMIT_PUSH_LITERAL_CONSTANT (stix, index);
GET_TOKEN (stix);
*/
break;
}
case STIX_IOTOK_APAREN:
/* TODO: array literal */
break;
case STIX_IOTOK_BPAREN:
/* TODO: byte array literal */
break;
case STIX_IOTOK_LBRACK:
/*
GET_TOKEN (stix);
if (parse_block_constructor(stix) <= -1) return -1;
*/
break;
case STIX_IOTOK_LPAREN:
GET_TOKEN (stix);
if (compile_method_expression(stix) <= -1) return -1;
if (stix->c->tok.type != STIX_IOTOK_RPAREN)
{
set_syntax_error (stix, STIX_SYNERR_RPAREN, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
GET_TOKEN (stix);
break;
default:
set_syntax_error (stix, STIX_SYNERR_PRIMARY, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
} }
if (compile_method_expression(stix) <= -1) return -1;
if (index > CODE_MAX_INDEX)
{
set_syntax_error (stix, STIX_SYNERR_ASSIGNEEUNEXP, assignee_loc, assignee);
return -1;
}
return emit_pop_and_store (stix, index, store_opcodes[var.type]);
} }
set_syntax_error (stix, STIX_SYNERR_ASSIGNEEUNDCL, assignee_loc, assignee); return 0;
return -1; }
static int compile_basic_expression (stix_t* stix, const stix_ucs_t* ident, const stix_ioloc_t* ident_loc)
{
/*
* basic-expression := expression-primary (method-messages method-cascaded-messages)?
*/
int is_super;
if (compile_expression_primary(stix, ident, ident_loc) <= -1) return -1;
#if 0 #if 0
if (stix->tok.type != STIX_IOTOK_EOF &&
if (stix_get_instance_variable_index (stx, stix->method_class, target, &i) == 0) stix->tok.type != STIX_IOTOK_RBRACE &&
stix->tok.type != STIX_IOTOK_PERIOD)
{ {
if (parse_expression(stix) == -1) return -1; if (parse_message_continuation(stix, is_super) == -1) return -1;
EMIT_STORE_RECEIVER_VARIABLE (stix, i);
return 0;
} }
if (stix_lookup_class_variable (stx, stix->method_class, target) != stx->nil)
{
if (parse_expression(stix) == -1) return -1;
/* TODO */
EMIT_CODE_TEST (stix, STIX_T("ASSIGN_CLASSVAR #"), target);
//EMIT_STORE_CLASS_VARIABLE (stix, target);
return 0;
}
/* TODO: IMPLEMENT POOL DICTIONARIES */
/* TODO: IMPLEMENT GLOBLAS, but i don't like this idea */
stix->errnum = STIX_stix_ERROR_UNDECLARED_NAME;
return -1;
#endif #endif
return 0;
} }
static int compile_method_expression (stix_t* stix) static int compile_method_expression (stix_t* stix)
{ {
/* /*
* method-expression := method-assignment-expression | method-basic-expression * method-expression := method-assignment-expression | basic-expression
* method-assignment-expression := identifier ":=" method-expression * method-assignment-expression := identifier ":=" method-expression
* method-basic-expression := method-expression-primary (message cascaded-message)? * basic-expression := method-expression-primary (message cascaded-message)?
*/ */
stix_ucs_t assignee; stix_ucs_t assignee;
@ -2456,13 +2494,13 @@ static int compile_method_expression (stix_t* stix)
} }
else else
{ {
if (compile_basic_expression(stix, &assignee) <= -1) goto oops; if (compile_basic_expression(stix, &assignee, &assignee_loc) <= -1) goto oops;
} }
} }
else else
{ {
assignee.len = 0; assignee.len = 0;
if (compile_basic_expression(stix, STIX_NULL) <= -1) goto oops; if (compile_basic_expression(stix, STIX_NULL, STIX_NULL) <= -1) goto oops;
} }
stix->c->mth.assignees.len -= assignee.len; stix->c->mth.assignees.len -= assignee.len;
@ -2479,11 +2517,13 @@ static int compile_method_statement (stix_t* stix)
* method-statement := method-return-statement | method-expression * method-statement := method-return-statement | method-expression
* method-return-statement := "^" method-expression * method-return-statement := "^" method-expression
*/ */
if (stix->c->tok.type == STIX_IOTOK_RETURN) if (stix->c->tok.type == STIX_IOTOK_RETURN)
{ {
/* handle the return statement */
GET_TOKEN (stix); GET_TOKEN (stix);
if (compile_method_expression(stix) <= -1) return -1; if (compile_method_expression(stix) <= -1) return -1;
return emit_code (stix, CODE_MAKE(CODE_SPECIAL, CODE_RETURN_MESSAGE_STACKTOP)); return emit_code (stix, CODE_RETURN_MESSAGE_STACKTOP);
} }
else else
{ {
@ -2521,7 +2561,7 @@ static int compile_method_statements (stix_t* stix)
} }
/* TODO: size optimization. emit code_return_receiver only if it's not previously emitted */ /* TODO: size optimization. emit code_return_receiver only if it's not previously emitted */
return emit_code (stix, CODE_MAKE(CODE_SPECIAL, CODE_RETURN_MESSAGE_RECEIVER)); return emit_code (stix, CODE_RETURN_MESSAGE_RECEIVER);
} }
static int add_compiled_method (stix_t* stix) static int add_compiled_method (stix_t* stix)

View File

@ -242,8 +242,11 @@ static char* syntax_error_msg[] =
"duplicate temporary variable name", "duplicate temporary variable name",
"duplicate variable name", "duplicate variable name",
"cannot assign to argument", "cannot assign to argument",
"undeclared assignee", "undeclared variable",
"assignee unexpressable in compiled code" "unusable variable in compiled code",
"inaccessible variable",
"wrong expression primary",
"wrong primitive number"
}; };
int main (int argc, char* argv[]) int main (int argc, char* argv[])

View File

@ -286,9 +286,12 @@ enum stix_synerrnum_t
STIX_SYNERR_ARGNAMEDUP, /* duplicate argument name */ STIX_SYNERR_ARGNAMEDUP, /* duplicate argument name */
STIX_SYNERR_TMPRNAMEDUP, /* duplicate temporary variable name */ STIX_SYNERR_TMPRNAMEDUP, /* duplicate temporary variable name */
STIX_SYNERR_VARNAMEDUP, /* duplicate variable name */ STIX_SYNERR_VARNAMEDUP, /* duplicate variable name */
STIX_SYNERR_ASSIGNEEARG, /* cannot assign to argument */ STIX_SYNERR_VARARG, /* cannot assign to argument */
STIX_SYNERR_ASSIGNEEUNDCL, /* undeclared assignee */ STIX_SYNERR_VARUNDCL, /* undeclared variable */
STIX_SYNERR_ASSIGNEEUNEXP /* assignee unexpressable in compiled code */ STIX_SYNERR_VARUNUSE, /* unsuable variable in compiled code */
STIX_SYNERR_VARINACC, /* inaccessible variable - e.g. accessing an instance variable from a class method is not allowed. */
STIX_SYNERR_PRIMARY, /* wrong expression primary */
STIX_SYNERR_PRIMITIVENO /* wrong primitive number */
}; };
typedef enum stix_synerrnum_t stix_synerrnum_t; typedef enum stix_synerrnum_t stix_synerrnum_t;

View File

@ -45,9 +45,10 @@ method-statements := method-statement ("." | ("." method-statements))*
method-statement := method-return-statement | method-expression method-statement := method-return-statement | method-expression
method-return-statement := "^" method-expression method-return-statement := "^" method-expression
method-expression := method-assignment-expression | method-basic-expression method-expression := method-assignment-expression | basic-expression
method-assignment-expression := identifier ":=" method-expression method-assignment-expression := identifier ":=" method-expression
method-basic-expression := method-expression-primary (message cascaded-message)? basic-expression := expression-primary (message cascaded-message)?
expression-primary := identifier | literal | block-constructor | ( "(" method-expression ")" )
---------------------------------------------------------- ----------------------------------------------------------