added a new modifier #variadic to make variadic method definition more obvious.

allowed the #primitive modifier in a method definition not associated with an external module.
fixed a bug in handling soft failure from numbered primitive functions
This commit is contained in:
hyunghwan.chung 2017-03-23 16:14:22 +00:00
parent 65722cf89b
commit 3fcfcff0ad
12 changed files with 475 additions and 177 deletions

View File

@ -328,13 +328,13 @@ class Apex(nil)
## ------------------------------------------------------- ## -------------------------------------------------------
## ------------------------------------------------------- ## -------------------------------------------------------
method(#class) perform() method(#class,#variadic) perform()
{ {
<primitive: #_perform> <primitive: #_perform>
self primitiveFailed self primitiveFailed
} }
method perform() method(#variadic) perform()
{ {
<primitive: #_perform> <primitive: #_perform>
self primitiveFailed self primitiveFailed
@ -540,85 +540,3 @@ extend Error
} }
} }
class System(Apex)
{
}
pooldic System.Log
{
## -----------------------------------------------------------
## defines log levels
## these items must follow defintions in moo.h
## -----------------------------------------------------------
DEBUG := 1.
INFO := 2.
WARN := 4.
ERROR := 8.
FATAL := 16.
}
extend System
{
## the following methods may not look suitable to be placed
## inside a system dictionary. but they are here for quick and dirty
## output production from the moo code.
## System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'.
##
method(#class) atLevel: level log: message
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level log: message and: message2
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level log: message and: message2 and: message3
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level logNl: message
{
## the #_log primitive accepts an array.
## so the following lines should work also.
## | x |
## x := Array new: 2.
## x at: 0 put: message.
## x at: 1 put: S'\n'.
## ^self atLevel: level log: x.
^self atLevel: level log: message and: S'\n'.
}
method(#class) atLevel: level logNl: message and: message2
{
^self atLevel: level log: message and: message2 and: S'\n'.
}
method(#class) log: message
{
^self atLevel: System.Log.INFO log: message.
}
method(#class) log: message and: message2
{
^self atLevel: System.Log.INFO log: message and: message2.
}
method(#class) logNl: message
{
^self atLevel: System.Log.INFO logNl: message.
}
method(#class) logNl: message and: message2
{
^self atLevel: System.Log.INFO logNl: message and: message2.
}
}

View File

@ -47,4 +47,9 @@ class(#pointer) Class(Apex)
]. ].
^false ^false
}*) }*)
method nsdic
{
^self.nsdic
}
} }

View File

@ -270,6 +270,10 @@ class MyObject(Object)
{ {
|a i| |a i|
System _getUint8(1,2).
'JJJJJJJJJJ' dump.
a := 100. a := 100.
## PROBLEM: the following double loop will exhaust the stack ## PROBLEM: the following double loop will exhaust the stack
(* (*
@ -318,16 +322,20 @@ class MyObject(Object)
} }
}*) }*)
System logNl: 'Sleeping start now....'.
(* basicAt: 12 to access the nsdic field. use a proper method once it's defined in Class *) (* basicAt: 12 to access the nsdic field. use a proper method once it's defined in Class *)
(System basicAt: 12) keysAndValuesDo: [:k :v | (System nsdic) keysAndValuesDo: [:k :v |
k dump. k dump.
v dump. v dump.
'------------' dump. '------------' dump.
]. ].
Processor sleepFor: 3. ## DEBUG VM... VM WAITING FOR 10 SECS instead of 3.
(System at: #Processor) dump.
System logNl: 'Sleeping start now....'.
Processor sleepFor: 2.
} }
(* (*

View File

@ -2,6 +2,7 @@
#include 'Context.moo'. #include 'Context.moo'.
#include 'Except.moo'. #include 'Except.moo'.
#include 'Class.moo'. #include 'Class.moo'.
#include 'System.moo'.
#include 'Boolean.moo'. #include 'Boolean.moo'.
#include 'Magnitu.moo'. #include 'Magnitu.moo'.
#include 'Collect.moo'. #include 'Collect.moo'.

View File

@ -42,7 +42,7 @@ class Stdio(Object) from 'stdio'
} }
*) *)
method format (fmt) method(#variadic) format (fmt)
{ {
| a b c | | a b c |
'THIS IS FORMAT' dump. 'THIS IS FORMAT' dump.

150
moo/kernel/System.moo Normal file
View File

@ -0,0 +1,150 @@
## TODO: consider if System can replace Apex itself.
## System, being the top class, seems to give very natural way of
## offering global system-level functions and interfaces.
##
## class System(nil) { ... }
## class Object(System) { .... }
## System at: #
## System logNl: 'xxxxx'.
## System getUint8(ptr,offset)
class System(Apex)
{
}
pooldic System.Log
{
## -----------------------------------------------------------
## defines log levels
## these items must follow defintions in moo.h
## -----------------------------------------------------------
DEBUG := 1.
INFO := 2.
WARN := 4.
ERROR := 8.
FATAL := 16.
}
extend System
{
## the following methods may not look suitable to be placed
## inside a system dictionary. but they are here for quick and dirty
## output production from the moo code.
## System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'.
##
method(#class) atLevel: level log: message
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level log: message and: message2
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level log: message and: message2 and: message3
{
<primitive: #_log>
## do nothing upon logging failure
}
method(#class) atLevel: level logNl: message
{
## the #_log primitive accepts an array.
## so the following lines should work also.
## | x |
## x := Array new: 2.
## x at: 0 put: message.
## x at: 1 put: S'\n'.
## ^self atLevel: level log: x.
^self atLevel: level log: message and: S'\n'.
}
method(#class) atLevel: level logNl: message and: message2
{
^self atLevel: level log: message and: message2 and: S'\n'.
}
method(#class) log: message
{
^self atLevel: System.Log.INFO log: message.
}
method(#class) log: message and: message2
{
^self atLevel: System.Log.INFO log: message and: message2.
}
method(#class) logNl: message
{
^self atLevel: System.Log.INFO logNl: message.
}
method(#class) logNl: message and: message2
{
^self atLevel: System.Log.INFO logNl: message and: message2.
}
(* nsdic access *)
method(#class) at: key
{
^self nsdic at: key
}
method(#class) at: key put: value
{
^self nsdic at: key put: value
}
(* raw memory access *)
method(#class,#primitive) _getInt8 (rawptr, offset). ## <primitive: #System__getInt8>
method(#class,#primitive) _getInt16 (rawptr, offset).
method(#class,#primitive) _getInt32 (rawptr, offset).
method(#class,#primitive) _getInt64 (rawptr, offset).
method(#class,#primitive) _getUint8 (rawptr, offset). ## <primitive: #System__getUint8>
method(#class,#primitive) _getUint16 (rawptr, offset).
method(#class,#primitive) _getUint32 (rawptr, offset).
method(#class,#primitive) _getUint64 (rawptr, offset).
(*
method(#class,#primitive) _putInt8 (rawptr, offset, value).
method(#class,#primitive) _putInt16 (rawptr, offset, value).
method(#class,#primitive) _putInt32 (rawptr, offset, value).
method(#class,#primitive) _putInt64 (rawptr, offset, value).
method(#class,#primitive) _putUint8 (rawptr, offset, value).
method(#class,#primitive) _putUint16 (rawptr, offset, value).
method(#class,#primitive) _putUint32 (rawptr, offset, value).
method(#class,#primitive) _putUint64 (rawptr, offset, value),
*)
(*
method(#class) getUint8: rawptr at: offset
{
<primitive: #_get_uint8>
}
method(#class) getUint16: rawptr at: offset
{
<primitive: #_get_uint16>
}
method(#class) getUint32: rawptr at: offset
{
<primitive: #_get_uint32>
}
method(#class) getUint64: rawptr at: offset
{
<primitive: #_get_uint64>
}
method(#class) putUint8: value rawptr: rawptr at: offset
{
<primitive: #_get_uint8>
}*)
}

View File

@ -81,6 +81,7 @@ class MyObject(Object)
'duplicate modifier' 'duplicate modifier'
'wrong method name' 'wrong method name'
'duplicate method name' 'duplicate method name'
'invalid variadic method definition'
'duplicate argument name' 'duplicate argument name'
'duplicate temporary variable name' 'duplicate temporary variable name'
'duplicate variable name' 'duplicate variable name'

View File

@ -116,6 +116,7 @@ static struct voca_t
{ 11, { 't','h','i','s','C','o','n','t','e','x','t' } }, { 11, { 't','h','i','s','C','o','n','t','e','x','t' } },
{ 11, { 't','h','i','s','P','r','o','c','e','s','s' } }, { 11, { 't','h','i','s','P','r','o','c','e','s','s' } },
{ 4, { 't','r','u','e' } }, { 4, { 't','r','u','e' } },
{ 9, { '#','v','a','r','i','a','d','i','c' } },
{ 5, { 'w','h','i','l','e' } }, { 5, { 'w','h','i','l','e' } },
{ 5, { '#','w','o','r','d' } }, { 5, { '#','w','o','r','d' } },
@ -162,6 +163,7 @@ enum voca_id_t
VOCA_THIS_CONTEXT, VOCA_THIS_CONTEXT,
VOCA_THIS_PROCESS, VOCA_THIS_PROCESS,
VOCA_TRUE, VOCA_TRUE,
VOCA_VARIADIC_S,
VOCA_WHILE, VOCA_WHILE,
VOCA_WORD_S, VOCA_WORD_S,
@ -3169,9 +3171,8 @@ static int compile_unary_method_name (moo_t* moo)
while (1); while (1);
} }
/* indicate that the unary method name is followed by a parameter list */
moo->c->mth.variadic = 1;
GET_TOKEN (moo); GET_TOKEN (moo);
return 9999; /* to indicate the method definition is in a procedural style */
} }
return 0; return 0;
@ -3288,6 +3289,13 @@ static int compile_method_name (moo_t* moo)
set_syntax_error (moo, MOO_SYNERR_MTHNAMEDUPL, &moo->c->mth.name_loc, &moo->c->mth.name); set_syntax_error (moo, MOO_SYNERR_MTHNAMEDUPL, &moo->c->mth.name_loc, &moo->c->mth.name);
return -1; return -1;
} }
/* compile_unary_method_name() returns 9999 if the name is followed by () */
if (moo->c->mth.variadic && n != 9999)
{
set_syntax_error (moo, MOO_SYNERR_VARIADMTHINVAL, &moo->c->mth.name_loc, &moo->c->mth.name);
return -1;
}
} }
MOO_ASSERT (moo, moo->c->mth.tmpr_nargs < MAX_CODE_NARGS); MOO_ASSERT (moo, moo->c->mth.tmpr_nargs < MAX_CODE_NARGS);
@ -5799,22 +5807,29 @@ static int compile_method_definition (moo_t* moo)
else if (is_token_symbol(moo, VOCA_PRIMITIVE_S)) else if (is_token_symbol(moo, VOCA_PRIMITIVE_S))
{ {
/* method(#primitive) */ /* method(#primitive) */
if (moo->c->cls.self_oop->modname == moo->_nil)
{
MOO_DEBUG2 (moo, "Disallowed #primitive method modifier in the class %.*js without 'from'\n",
MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->name),
MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->name));
set_syntax_error (moo, MOO_SYNERR_MODIFIERBANNED, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
if (moo->c->mth.primitive) if (moo->c->mth.primitive)
{ {
/* #primitive duplicate modifier */
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo)); set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1; return -1;
} }
moo->c->mth.primitive = 1; moo->c->mth.primitive = 1;
GET_TOKEN (moo);
}
else if (is_token_symbol(moo, VOCA_VARIADIC_S))
{
/* method(#variadic) */
if (moo->c->mth.variadic)
{
/* #variadic duplicate modifier */
set_syntax_error (moo, MOO_SYNERR_MODIFIERDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
moo->c->mth.variadic = 1;
GET_TOKEN (moo); GET_TOKEN (moo);
} }
else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN) else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN)
@ -5853,9 +5868,6 @@ static int compile_method_definition (moo_t* moo)
/* the primitive method must be of this form /* the primitive method must be of this form
* method(#primitive) method_name. * method(#primitive) method_name.
*/ */
moo_oow_t litidx, savedlen;
moo_oocs_t tmp;
if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD) if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD)
{ {
/* . expected */ /* . expected */
@ -5863,16 +5875,55 @@ static int compile_method_definition (moo_t* moo)
return -1; return -1;
} }
/* TODO: i can check if the primitive method is available at compile time by querying the module. if (moo->c->cls.self_oop->modname == moo->_nil)
* do the check depending on the compiler option */ {
moo_oow_t savedlen;
moo_ooi_t pfnum;
savedlen = moo->c->cls.modname.len;
/* primitive identifer = classname_methodname
* let me compose the identifer into the back of the cls.modname buffer.
* i'll revert it when done */
if (copy_string_to (moo, &moo->c->cls.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 ||
copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '_') <= -1)
{
moo->c->cls.modname.len = savedlen;
return -1;
}
pfnum = moo_getpfnum (moo, &moo->c->cls.modname.ptr[savedlen], moo->c->cls.modname.len - savedlen);
if (pfnum <= -1 || !MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(pfnum))
{
MOO_DEBUG2 (moo, "Cannot find intrinsic primitive handler - %.*js\n",
moo->c->cls.modname.len - savedlen, &moo->c->cls.modname.ptr[savedlen]);
moo->c->cls.modname.len = savedlen;
set_syntax_error (moo, MOO_SYNERR_PFIDINVAL, &moo->c->mth.name_loc, &moo->c->mth.name);
return -1;
}
moo->c->cls.modname.len = savedlen;
moo->c->mth.pftype = PFTYPE_NUMBERED;
moo->c->mth.pfnum = pfnum;
}
else
{
moo_oow_t litidx, savedlen;
moo_oocs_t tmp;
/* combine the module name and the method name delimited by a period /* combine the module name and the method name delimited by a period
* when doing it, let me reuse the cls.modname buffer and restore it * when doing it, let me reuse the cls.modname buffer and restore it
* back once done */ * back once done */
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->c->cls.self_oop->modname) == moo->_symbol);
savedlen = moo->c->cls.modname.len; savedlen = moo->c->cls.modname.len;
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->c->cls.self_oop->modname) == moo->_symbol);
tmp.ptr = MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->modname); tmp.ptr = MOO_OBJ_GET_CHAR_SLOT(moo->c->cls.self_oop->modname);
tmp.len = MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->modname); tmp.len = MOO_OBJ_GET_SIZE(moo->c->cls.self_oop->modname);
/* TODO: i can check if the primitive method is available at compile time by querying the module.
* do the check depending on the compiler option */
if (copy_string_to (moo, &tmp, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 || if (copy_string_to (moo, &tmp, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '\0') <= -1 ||
copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '.') <= -1 || copy_string_to (moo, &moo->c->mth.name, &moo->c->cls.modname, &moo->c->cls.modname_capa, 1, '.') <= -1 ||
add_symbol_literal(moo, &moo->c->cls.modname, savedlen, &litidx) <= -1) add_symbol_literal(moo, &moo->c->cls.modname, savedlen, &litidx) <= -1)
@ -5880,6 +5931,7 @@ static int compile_method_definition (moo_t* moo)
moo->c->cls.modname.len = savedlen; moo->c->cls.modname.len = savedlen;
return -1; return -1;
} }
moo->c->cls.modname.len = savedlen; moo->c->cls.modname.len = savedlen;
/* the symbol added must be the first literal to the current method. /* the symbol added must be the first literal to the current method.
@ -5890,6 +5942,7 @@ static int compile_method_definition (moo_t* moo)
moo->c->mth.pftype = PFTYPE_NAMED; moo->c->mth.pftype = PFTYPE_NAMED;
moo->c->mth.pfnum = litidx; moo->c->mth.pfnum = litidx;
} }
}
else else
{ {
if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE) if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE)

View File

@ -107,33 +107,33 @@ static moo_ooch_t synerrstr_35[] = {'d','i','s','a','l','l','o','w','e','d',' ',
static moo_ooch_t synerrstr_36[] = {'d','u','p','l','i','c','a','t','e',' ','m','o','d','i','f','i','e','r','\0'}; static moo_ooch_t synerrstr_36[] = {'d','u','p','l','i','c','a','t','e',' ','m','o','d','i','f','i','e','r','\0'};
static moo_ooch_t synerrstr_37[] = {'w','r','o','n','g',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_37[] = {'w','r','o','n','g',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_38[] = {'d','u','p','l','i','c','a','t','e',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_38[] = {'d','u','p','l','i','c','a','t','e',' ','m','e','t','h','o','d',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_39[] = {'d','u','p','l','i','c','a','t','e',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_39[] = {'i','n','v','a','l','i','d',' ','v','a','r','i','a','d','i','c',' ','m','e','t','h','o','d',' ','d','e','f','i','n','i','t','i','o','n','\0'};
static moo_ooch_t synerrstr_40[] = {'d','u','p','l','i','c','a','t','e',' ','t','e','m','p','o','r','a','r','y',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_40[] = {'d','u','p','l','i','c','a','t','e',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_41[] = {'d','u','p','l','i','c','a','t','e',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_41[] = {'d','u','p','l','i','c','a','t','e',' ','t','e','m','p','o','r','a','r','y',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_42[] = {'d','u','p','l','i','c','a','t','e',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_42[] = {'d','u','p','l','i','c','a','t','e',' ','v','a','r','i','a','b','l','e',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_43[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'}; static moo_ooch_t synerrstr_43[] = {'d','u','p','l','i','c','a','t','e',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_44[] = {'u','n','u','s','a','b','l','e',' ','v','a','r','i','a','b','l','e',' ','i','n',' ','c','o','m','p','i','l','e','d',' ','c','o','d','e','\0'}; static moo_ooch_t synerrstr_44[] = {'u','n','d','e','c','l','a','r','e','d',' ','v','a','r','i','a','b','l','e','\0'};
static moo_ooch_t synerrstr_45[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','v','a','r','i','a','b','l','e','\0'}; static moo_ooch_t synerrstr_45[] = {'u','n','u','s','a','b','l','e',' ','v','a','r','i','a','b','l','e',' ','i','n',' ','c','o','m','p','i','l','e','d',' ','c','o','d','e','\0'};
static moo_ooch_t synerrstr_46[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'}; static moo_ooch_t synerrstr_46[] = {'i','n','a','c','c','e','s','s','i','b','l','e',' ','v','a','r','i','a','b','l','e','\0'};
static moo_ooch_t synerrstr_47[] = {'w','r','o','n','g',' ','e','x','p','r','e','s','s','i','o','n',' ','p','r','i','m','a','r','y','\0'}; static moo_ooch_t synerrstr_47[] = {'a','m','b','i','g','u','o','u','s',' ','v','a','r','i','a','b','l','e','\0'};
static moo_ooch_t synerrstr_48[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; static moo_ooch_t synerrstr_48[] = {'w','r','o','n','g',' ','e','x','p','r','e','s','s','i','o','n',' ','p','r','i','m','a','r','y','\0'};
static moo_ooch_t synerrstr_49[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'}; static moo_ooch_t synerrstr_49[] = {'t','o','o',' ','m','a','n','y',' ','t','e','m','p','o','r','a','r','i','e','s','\0'};
static moo_ooch_t synerrstr_50[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','t','e','m','p','o','r','a','r','i','e','s','\0'}; static moo_ooch_t synerrstr_50[] = {'t','o','o',' ','m','a','n','y',' ','a','r','g','u','m','e','n','t','s','\0'};
static moo_ooch_t synerrstr_51[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t','s','\0'}; static moo_ooch_t synerrstr_51[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','t','e','m','p','o','r','a','r','i','e','s','\0'};
static moo_ooch_t synerrstr_52[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'}; static moo_ooch_t synerrstr_52[] = {'t','o','o',' ','m','a','n','y',' ','b','l','o','c','k',' ','a','r','g','u','m','e','n','t','s','\0'};
static moo_ooch_t synerrstr_53[] = {'t','o','o',' ','l','a','r','g','e',' ','a','r','r','a','y',' ','e','x','p','r','e','s','s','i','o','n','\0'}; static moo_ooch_t synerrstr_53[] = {'t','o','o',' ','l','a','r','g','e',' ','b','l','o','c','k','\0'};
static moo_ooch_t synerrstr_54[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'}; static moo_ooch_t synerrstr_54[] = {'t','o','o',' ','l','a','r','g','e',' ','a','r','r','a','y',' ','e','x','p','r','e','s','s','i','o','n','\0'};
static moo_ooch_t synerrstr_55[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'}; static moo_ooch_t synerrstr_55[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','n','u','m','b','e','r','\0'};
static moo_ooch_t synerrstr_56[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_56[] = {'w','r','o','n','g',' ','p','r','i','m','i','t','i','v','e',' ','f','u','n','c','t','i','o','n',' ','i','d','e','n','t','i','f','i','e','r','\0'};
static moo_ooch_t synerrstr_57[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'}; static moo_ooch_t synerrstr_57[] = {'w','r','o','n','g',' ','m','o','d','u','l','e',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_58[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_58[] = {'#','i','n','c','l','u','d','e',' ','e','r','r','o','r','\0'};
static moo_ooch_t synerrstr_59[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_59[] = {'w','r','o','n','g',' ','n','a','m','e','s','p','a','c','e',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_60[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'}; static moo_ooch_t synerrstr_60[] = {'w','r','o','n','g',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_61[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'}; static moo_ooch_t synerrstr_61[] = {'d','u','p','l','i','c','a','t','e',' ','p','o','o','l',' ','d','i','c','t','i','o','n','a','r','y',' ','n','a','m','e','\0'};
static moo_ooch_t synerrstr_62[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'}; static moo_ooch_t synerrstr_62[] = {'l','i','t','e','r','a','l',' ','e','x','p','e','c','t','e','d','\0'};
static moo_ooch_t synerrstr_63[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'}; static moo_ooch_t synerrstr_63[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','n','o','t',' ','w','i','t','h','i','n',' ','a',' ','l','o','o','p','\0'};
static moo_ooch_t synerrstr_64[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'}; static moo_ooch_t synerrstr_64[] = {'b','r','e','a','k',' ','o','r',' ','c','o','n','t','i','n','u','e',' ','w','i','t','h','i','n',' ','a',' ','b','l','o','c','k','\0'};
static moo_ooch_t synerrstr_65[] = {'w','h','i','l','e',' ','e','x','p','e','c','t','e','d','\0'};
static moo_ooch_t* synerrstr[] = static moo_ooch_t* synerrstr[] =
{ {
synerrstr_0, synerrstr_1, synerrstr_2, synerrstr_3, synerrstr_4, synerrstr_5, synerrstr_6, synerrstr_7, synerrstr_0, synerrstr_1, synerrstr_2, synerrstr_3, synerrstr_4, synerrstr_5, synerrstr_6, synerrstr_7,
@ -144,7 +144,7 @@ static moo_ooch_t* synerrstr[] =
synerrstr_40, synerrstr_41, synerrstr_42, synerrstr_43, synerrstr_44, synerrstr_45, synerrstr_46, synerrstr_47, synerrstr_40, synerrstr_41, synerrstr_42, synerrstr_43, synerrstr_44, synerrstr_45, synerrstr_46, synerrstr_47,
synerrstr_48, synerrstr_49, synerrstr_50, synerrstr_51, synerrstr_52, synerrstr_53, synerrstr_54, synerrstr_55, synerrstr_48, synerrstr_49, synerrstr_50, synerrstr_51, synerrstr_52, synerrstr_53, synerrstr_54, synerrstr_55,
synerrstr_56, synerrstr_57, synerrstr_58, synerrstr_59, synerrstr_60, synerrstr_61, synerrstr_62, synerrstr_63, synerrstr_56, synerrstr_57, synerrstr_58, synerrstr_59, synerrstr_60, synerrstr_61, synerrstr_62, synerrstr_63,
synerrstr_64 synerrstr_64, synerrstr_65
}; };
#endif #endif
/* END: GENERATED WITH generr.moo */ /* END: GENERATED WITH generr.moo */

View File

@ -1739,6 +1739,139 @@ static moo_pfrc_t pf_hash (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
static moo_pfrc_t _get_raw_int (moo_t* moo, moo_ooi_t nargs, int size)
{
moo_uint8_t* rawptr;
moo_oow_t offset;
moo_ooi_t value;
moo_oop_t result;
if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 0), (moo_oow_t*)&rawptr) <= 0 ||
moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 1), &offset) <= 0)
{
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
switch (size)
{
case 1:
value = *(moo_int8_t*)&rawptr[offset];
break;
case 2:
value = *(moo_int16_t*)&rawptr[offset];
break;
case 4:
value = *(moo_int32_t*)&rawptr[offset];
break;
case 8:
value = *(moo_int64_t*)&rawptr[offset];
break;
default:
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
result = moo_ooitoint (moo, value);
if (!result) return MOO_PF_FAILURE;
MOO_STACK_SETRET (moo, nargs, result);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t _get_raw_uint (moo_t* moo, moo_ooi_t nargs, int size)
{
moo_uint8_t* rawptr;
moo_oow_t offset;
moo_oow_t value;
moo_oop_t result;
MOO_DEBUG1 (moo, "get_raw_uint ..%d\n", size);
if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 0), (moo_oow_t*)&rawptr) <= 0 ||
moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 1), &offset) <= 0)
{
MOO_DEBUG0 (moo, "get_raw_uint failure...\n");
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
switch (size)
{
case 1:
value = *(moo_uint8_t*)&rawptr[offset];
break;
case 2:
value = *(moo_uint16_t*)&rawptr[offset];
break;
case 4:
value = *(moo_uint32_t*)&rawptr[offset];
break;
case 8:
value = *(moo_uint64_t*)&rawptr[offset];
break;
default:
moo->errnum = MOO_EINVAL;
return MOO_PF_FAILURE;
}
result = moo_oowtoint (moo, value);
if (!result) return MOO_PF_FAILURE;
MOO_DEBUG1 (moo, "get_raw_uint failure..%O.\n", result);
MOO_STACK_SETRET (moo, nargs, result);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_get_int8 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_int (moo, nargs, 1);
}
static moo_pfrc_t pf_get_int16 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_int (moo, nargs, 2);
}
static moo_pfrc_t pf_get_int32 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_int (moo, nargs, 4);
}
static moo_pfrc_t pf_get_int64 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_int (moo, nargs, 8);
}
static moo_pfrc_t pf_get_uint8 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_uint (moo, nargs, 1);
}
static moo_pfrc_t pf_get_uint16 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_uint (moo, nargs, 2);
}
static moo_pfrc_t pf_get_uint32 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_uint (moo, nargs, 4);
}
static moo_pfrc_t pf_get_uint64 (moo_t* moo, moo_ooi_t nargs)
{
return _get_raw_uint (moo, nargs, 8);
}
static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_responds_to (moo_t* moo, moo_ooi_t nargs)
{ {
moo_oop_t rcv, selector; moo_oop_t rcv, selector;
@ -1896,7 +2029,7 @@ static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_o
if (MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs) != actual_arg_count /* nargs */) if (MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs) != actual_arg_count /* nargs */)
{ {
MOO_LOG4 (moo, MOO_LOG_PRIMITIVE | MOO_LOG_ERROR, MOO_LOG4 (moo, MOO_LOG_PRIMITIVE | MOO_LOG_ERROR,
"Error(%hs) - wrong number of arguments to a block context %O - expecting %zd, got %zd\n", "Error(%hs) - wrong number of arguments to a block context %O - %zd expected, %zd given\n",
__PRIMITIVE_NAME__, rcv_blkctx, MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs), actual_arg_count); __PRIMITIVE_NAME__, rcv_blkctx, MOO_OOP_TO_SMOOI(rcv_blkctx->method_or_nargs), actual_arg_count);
return MOO_PF_FAILURE; return MOO_PF_FAILURE;
} }
@ -2759,11 +2892,11 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_ooi_t nargs)
} }
#define MAX_NARGS MOO_TYPE_MAX(moo_ooi_t) #define MAX_NARGS MOO_TYPE_MAX(moo_oow_t)
struct pf_t struct pf_t
{ {
moo_ooi_t min_nargs; /* expected number of arguments */ moo_oow_t min_nargs; /* expected number of arguments */
moo_ooi_t max_nargs; /* expected number of arguments */ moo_oow_t max_nargs; /* expected number of arguments */
moo_pfimpl_t handler; moo_pfimpl_t handler;
const char* name; /* the name is supposed to be 7-bit ascii only */ const char* name; /* the name is supposed to be 7-bit ascii only */
}; };
@ -2791,6 +2924,26 @@ static pf_t pftab[] =
{ 0, 0, pf_hash, "_hash" }, { 0, 0, pf_hash, "_hash" },
{ 2, 2, pf_get_int8, "System__getInt8" },
{ 2, 2, pf_get_int16, "System__getInt16" },
{ 2, 2, pf_get_int32, "System__getInt32" },
{ 2, 2, pf_get_int64, "System__getInt64" },
{ 2, 2, pf_get_uint8, "System__getUint8" },
{ 2, 2, pf_get_uint16, "System__getUint16" },
{ 2, 2, pf_get_uint32, "System__getUint32" },
{ 2, 2, pf_get_uint64, "System__getUint64" },
/*
{ 3, 3, pf_put_int8, "System__putInt8" },
{ 3, 3, pf_put_int16, "System__putInt16" },
{ 3, 3, pf_put_int32, "System__putInt32" },
{ 3, 3, pf_put_int64, "System__putInt64" },
{ 3, 3, pf_put_uint8, "System__putUint8" },
{ 3, 3, pf_put_uint16, "System__putUint16" },
{ 3, 3, pf_put_uint32, "System__putUint32" },
{ 3, 3, pf_put_uint64, "System__putUint64" },
*/
{ 1, 1, pf_responds_to, "_responds_to" }, { 1, 1, pf_responds_to, "_responds_to" },
{ 1, MAX_NARGS, pf_perform, "_perform" }, { 1, MAX_NARGS, pf_perform, "_perform" },
{ 1, 1, pf_exceptionize_error, "_exceptionize_error" }, { 1, 1, pf_exceptionize_error, "_exceptionize_error" },
@ -2799,7 +2952,6 @@ static pf_t pftab[] =
{ 0, MAX_NARGS, pf_block_value, "_block_value" }, { 0, MAX_NARGS, pf_block_value, "_block_value" },
{ 0, MAX_NARGS, pf_block_new_process, "_block_new_process" }, { 0, MAX_NARGS, pf_block_new_process, "_block_new_process" },
{ 0, 0, pf_process_resume, "_process_resume" }, { 0, 0, pf_process_resume, "_process_resume" },
{ 0, 0, pf_process_terminate, "_process_terminate" }, { 0, 0, pf_process_terminate, "_process_terminate" },
{ 0, 0, pf_process_yield, "_process_yield" }, { 0, 0, pf_process_yield, "_process_yield" },
@ -2852,10 +3004,7 @@ int moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len)
/* TODO: have the pftable sorted alphabetically and do binary search */ /* TODO: have the pftable sorted alphabetically and do binary search */
for (i = 0; i < MOO_COUNTOF(pftab); i++) for (i = 0; i < MOO_COUNTOF(pftab); i++)
{ {
if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) if (moo_compoocharsbcstr(ptr, len, pftab[i].name) == 0) return i;
{
return i;
}
} }
moo->errnum = MOO_ENOENT; moo->errnum = MOO_ENOENT;
@ -2866,6 +3015,7 @@ int moo_getpfnum (moo_t* moo, const moo_ooch_t* ptr, moo_oow_t len)
static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs) static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
{ {
moo_ooi_t preamble, preamble_code; moo_ooi_t preamble, preamble_code;
moo_ooi_t /*sp,*/ stack_base;
#if defined(MOO_DEBUG_VM_EXEC) #if defined(MOO_DEBUG_VM_EXEC)
moo_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */ moo_ooi_t fetched_instruction_pointer = 0; /* set it to a fake value */
@ -2982,24 +3132,36 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
{ {
moo_ooi_t pfnum; moo_ooi_t pfnum;
stack_base = moo->sp - nargs - 1; /* stack base before receiver and arguments */
pfnum = MOO_METHOD_GET_PREAMBLE_INDEX(preamble); pfnum = MOO_METHOD_GET_PREAMBLE_INDEX(preamble);
LOG_INST_1 (moo, "preamble_primitive %zd", pf_no); LOG_INST_1 (moo, "preamble_primitive %zd", pf_no);
if (pfnum >= 0 && pfnum < MOO_COUNTOF(pftab) && if (pfnum >= 0 && pfnum < MOO_COUNTOF(pftab))
(nargs >= pftab[pfnum].min_nargs && nargs <= pftab[pfnum].max_nargs))
{ {
int n; int n;
if ((nargs < pftab[pfnum].min_nargs || nargs > pftab[pfnum].max_nargs))
{
MOO_DEBUG4 (moo, "Soft failure due to argument count mismatch for primitive function %hs - %zu-%zu expected, %zu given\n",
pftab[pfnum].name, pftab[pfnum].min_nargs, pftab[pfnum].max_nargs, nargs);
goto activate_primitive_method_body;
}
moo_pushtmp (moo, (moo_oop_t*)&method); moo_pushtmp (moo, (moo_oop_t*)&method);
n = pftab[pfnum].handler (moo, nargs); n = pftab[pfnum].handler (moo, nargs);
moo_poptmp (moo); moo_poptmp (moo);
if (n <= MOO_PF_HARD_FAILURE) return -1; if (n <= MOO_PF_HARD_FAILURE) return -1;
if (n >= MOO_PF_SUCCESS) break; if (n >= MOO_PF_SUCCESS) break;
MOO_DEBUG2 (moo, "Soft failure indicated by primitive function %p - %hs\n", pftab[pfnum].handler, pftab[pfnum].name);
}
else
{
MOO_DEBUG1 (moo, "Cannot call primitive numbered %zd - invalid number\n", pfnum);
} }
/* soft primitive failure */ goto activate_primitive_method_body;
if (activate_new_method (moo, method, nargs) <= -1) return -1;
break;
} }
case MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE: case MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE:
@ -3008,10 +3170,8 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
moo_oop_t name; moo_oop_t name;
moo_pfimpl_t handler; moo_pfimpl_t handler;
moo_oow_t w; moo_oow_t w;
moo_ooi_t /*sp,*/ sb;
/*sp = moo->sp;*/ stack_base = moo->sp - nargs - 1; /* stack base before receiver and arguments */
sb = moo->sp - nargs - 1; /* stack base before receiver and arguments */
#if !defined(NDEBUG) #if !defined(NDEBUG)
pf_name_index = MOO_METHOD_GET_PREAMBLE_INDEX(preamble); pf_name_index = MOO_METHOD_GET_PREAMBLE_INDEX(preamble);
@ -3072,6 +3232,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
MOO_DEBUG2 (moo, "Soft failure for non-existent primitive function - %.*js\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot); MOO_DEBUG2 (moo, "Soft failure for non-existent primitive function - %.*js\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot);
} }
activate_primitive_method_body:
#if defined(MOO_USE_METHOD_TRAILER) #if defined(MOO_USE_METHOD_TRAILER)
MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method)); MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_TRAILER(method));
if (MOO_METHOD_GET_CODE_SIZE(method) == 0) /* this trailer size field not a small integer */ if (MOO_METHOD_GET_CODE_SIZE(method) == 0) /* this trailer size field not a small integer */
@ -3079,11 +3240,10 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
if (method->code == moo->_nil) if (method->code == moo->_nil)
#endif #endif
{ {
/* no byte code to execute */ /* no byte code to execute - make it a hard failure */
/* TODO: what is the best tactics? emulate "self primitiveFailed"? */ /* TODO: what is the best tactics? emulate "self primitiveFailed"? or should this be generated by the compiler */
MOO_DEBUG0 (moo, "Empty primitive body\n");
/* force restore stack pointers */ moo->sp = stack_base; /* force restore stack pointer */
moo->sp = sb;
MOO_STACK_PUSH (moo, moo->_nil); MOO_STACK_PUSH (moo, moo->_nil);
return -1; return -1;
} }
@ -3091,6 +3251,7 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
{ {
if (activate_new_method (moo, method, nargs) <= -1) return -1; if (activate_new_method (moo, method, nargs) <= -1) return -1;
} }
break; break;
} }

View File

@ -1014,7 +1014,7 @@ static void vm_muxwait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_c
if (xtn->ev.len <= 0) if (xtn->ev.len <= 0)
{ {
/* the event buffer is still empty */ /* the event buffer is still empty */
pthread_cond_wait (&xtn->ev.cnd2, &xtn->ev.mtx); pthread_cond_timedwait (&xtn->ev.cnd2, &xtn->ev.mtx, &ts);
} }
pthread_mutex_unlock (&xtn->ev.mtx); pthread_mutex_unlock (&xtn->ev.mtx);
} }
@ -1151,7 +1151,7 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
#if defined(USE_THREAD) #if defined(USE_THREAD)
/* the sleep callback is called only if there is no IO semaphore /* the sleep callback is called only if there is no IO semaphore
* waiting. so i can safely call vm_muxwait() wihtout a muxwait callback * waiting. so i can safely call vm_muxwait() without a muxwait callback
* when USE_THREAD is true */ * when USE_THREAD is true */
vm_muxwait (moo, dur, MOO_NULL); vm_muxwait (moo, dur, MOO_NULL);
#else #else

View File

@ -1229,6 +1229,7 @@ enum moo_synerrnum_t
MOO_SYNERR_MODIFIERDUPL, /* duplicate modifier */ MOO_SYNERR_MODIFIERDUPL, /* duplicate modifier */
MOO_SYNERR_MTHNAME, /* wrong method name */ MOO_SYNERR_MTHNAME, /* wrong method name */
MOO_SYNERR_MTHNAMEDUPL, /* duplicate method name */ MOO_SYNERR_MTHNAMEDUPL, /* duplicate method name */
MOO_SYNERR_VARIADMTHINVAL, /* invalid variadic method definition */
MOO_SYNERR_ARGNAMEDUPL, /* duplicate argument name */ MOO_SYNERR_ARGNAMEDUPL, /* duplicate argument name */
MOO_SYNERR_TMPRNAMEDUPL, /* duplicate temporary variable name */ MOO_SYNERR_TMPRNAMEDUPL, /* duplicate temporary variable name */
MOO_SYNERR_VARNAMEDUPL, /* duplicate variable name */ MOO_SYNERR_VARNAMEDUPL, /* duplicate variable name */