00001
00013
00014 #include <stdlib.h>
00015
00016 #include "NewtErrs.h"
00017 #include "NewtVM.h"
00018 #include "NewtBC.h"
00019 #include "NewtGC.h"
00020 #include "NewtMem.h"
00021 #include "NewtEnv.h"
00022 #include "NewtObj.h"
00023 #include "NewtFns.h"
00024 #include "NewtStr.h"
00025 #include "NewtFile.h"
00026 #include "NewtIO.h"
00027 #include "NewtPrint.h"
00028 #include "NewtNSOF.h"
00029
00030
00031
00032 typedef void(*instruction_t)(int16_t b);
00033 typedef void(*simple_instruction_t)(void);
00034 typedef newtRef(*nvm_func_t)();
00035
00036
00037
00038 vm_env_t vm_env;
00039
00040
00041 #pragma mark -
00042
00043
00044 #define START_LOCALARGS 3
00045
00046
00047 #define BC (vm_env.bc)
00048 #define BCLEN (vm_env.bclen)
00049
00050 #define CALLSTACK ((vm_reg_t *)vm_env.callstack.stackp)
00051 #define CALLSP (vm_env.callstack.sp)
00052 #define EXCPSTACK ((vm_excp_t *)vm_env.excpstack.stackp)
00053 #define EXCPSP (vm_env.excpstack.sp)
00054 #define CURREXCP (vm_env.currexcp)
00055
00056 #define REG (vm_env.reg)
00057 #define STACK ((newtRef *)vm_env.stack.stackp)
00058
00059 #define FUNC ((REG).func)
00060 #define PC ((REG).pc)
00061 #define SP ((REG).sp)
00062 #define LOCALS ((REG).locals)
00063 #define RCVR ((REG).rcvr)
00064 #define IMPL ((REG).impl)
00065
00066
00067 #pragma mark -
00068
00069
00070 static newtErr NVMGetExceptionErrCode(newtRefArg r, bool dump);
00071 static newtRef NVMMakeExceptionFrame(newtRefArg name, newtRefArg data);
00072 static void NVMClearCurrException(void);
00073
00074 static void NVMSetFn(newtRefArg fn);
00075 static void NVMNoStackFrameForReturn(void);
00076
00077 static void reg_rewind(int32_t sp);
00078 static void reg_pop(void);
00079 static void reg_push(int32_t sp);
00080 static void reg_save(int32_t sp);
00081
00082 static newtRef stk_pop0(void);
00083 static newtRef stk_pop(void);
00084 static void stk_pop_n(int32_t n, newtRef a[]);
00085 static void stk_remove(uint16_t n);
00086 static newtRef stk_top(void);
00087 static void stk_push(newtRefArg value);
00088
00089 static bool excp_push(newtRefArg sym, newtRefArg pc);
00090 static void excp_pop(void);
00091 static vm_excp_t * excp_top(void);
00092 static void excp_pop_handlers(void);
00093
00094 static newtRef liter_get(int16_t n);
00095
00096 static newtRef iter_new(newtRefArg r, newtRefArg deeply);
00097 static void iter_next(newtRefArg iter);
00098 static bool iter_done(newtRefArg iter);
00099
00100 static newtRef NVMMakeArgsArray(uint16_t numArgs);
00101 static void NVMBindArgs(uint16_t numArgs);
00102 static void NVMThrowBC(newtErr err, newtRefArg value, int16_t pop, bool push);
00103 static newtErr NVMFuncCheck(newtRefArg fn, int16_t numArgs);
00104 static void NVMCallNativeFn(newtRefArg fn, int16_t numArgs);
00105 static void NVMCallNativeFunc(newtRefArg fn, newtRefArg rcvr, int16_t numArgs);
00106 static void NVMFuncCall(newtRefArg fn, int16_t numArgs);
00107 static void NVMMessageSend(newtRefArg impl, newtRefArg receiver, newtRefArg fn, int16_t numArgs);
00108
00109 static newtRef vm_send(int16_t b, newtErr * errP);
00110 static newtRef vm_resend(int16_t b, newtErr * errP);
00111
00112 static void si_pop(void);
00113 static void si_dup(void);
00114 static void si_return(void);
00115 static void si_pushself(void);
00116 static void si_set_lex_scope(void);
00117 static void si_iternext(void);
00118 static void si_iterdone(void);
00119 static void si_pop_handlers(void);
00120
00121 static void fn_add(void);
00122 static void fn_subtract(void);
00123 static void fn_aref(void);
00124 static void fn_set_aref(void);
00125 static void fn_equals(void);
00126 static void fn_not(void);
00127 static void fn_not_equals(void);
00128 static void fn_multiply(void);
00129 static void fn_divide(void);
00130 static void fn_div(void);
00131 static void fn_less_than(void);
00132 static void fn_greater_than(void);
00133 static void fn_greater_or_equal(void);
00134 static void fn_less_or_equal(void);
00135 static void fn_bit_and(void);
00136 static void fn_bit_or(void);
00137 static void fn_bit_not(void);
00138 static void fn_new_iterator(void);
00139 static void fn_length(void);
00140 static void fn_clone(void);
00141 static void fn_set_class(void);
00142 static void fn_add_array_slot(void);
00143 static void fn_stringer(void);
00144 static void fn_has_path(void);
00145 static void fn_classof(void);
00146
00147 static void is_dummy(int16_t b);
00148 static void is_simple_instructions(int16_t b);
00149 static void is_push(int16_t b);
00150 static void is_push_constant(int16_t b);
00151 static void is_call(int16_t b);
00152 static void is_invoke(int16_t b);
00153 static void is_send(int16_t b);
00154 static void is_send_if_defined(int16_t b);
00155 static void is_resend(int16_t b);
00156 static void is_resend_if_defined(int16_t b);
00157 static void is_branch(int16_t b);
00158 static void is_branch_if_true(int16_t b);
00159 static void is_branch_if_false(int16_t b);
00160 static void is_find_var(int16_t b);
00161 static void is_get_var(int16_t b);
00162 static void is_make_frame(int16_t b);
00163 static void is_make_array(int16_t b);
00164 static void is_get_path(int16_t b);
00165 static void is_set_path(int16_t b);
00166 static void is_set_var(int16_t b);
00167 static void is_find_and_set_var(int16_t b);
00168 static void is_incr_var(int16_t b);
00169 static void is_branch_if_loop_not_done(int16_t b);
00170 static void is_freq_func(int16_t b);
00171 static void is_new_handlers(int16_t b);
00172
00173 static void NVMDumpInstResult(FILE * f);
00174 static void NVMDumpInstCode(FILE * f, uint8_t * bc, uint32_t pc, uint16_t len);
00175
00176 static void NVMInitREG(void);
00177 static void NVMInitSTACK(void);
00178 static void NVMCleanSTACK(void);
00179
00180 static void NVMInitGlobalFns0(void);
00181 static void NVMInitGlobalFns1(void);
00182 static void NVMInitExGlobalFns(void);
00183 static void NVMInitDebugGlobalFns(void);
00184 static void NVMInitGlobalFns(void);
00185
00186 static void NVMInitGlobalVars(void);
00187
00188 static void NVMInit(void);
00189 static void NVMClean(void);
00190 static void NVMLoop(uint32_t callsp);
00191
00192 static newtRef NVMInterpret2(nps_syntax_node_t * stree, uint32_t numStree, newtErr * errP);
00193
00194
00195
00196
00198 static simple_instruction_t simple_instructions[] =
00199 {
00200 si_pop,
00201 si_dup,
00202 si_return,
00203 si_pushself,
00204 si_set_lex_scope,
00205 si_iternext,
00206 si_iterdone,
00207 si_pop_handlers
00208 };
00209
00210
00212 static simple_instruction_t fn_instructions[] =
00213 {
00214 fn_add,
00215 fn_subtract,
00216 fn_aref,
00217 fn_set_aref,
00218 fn_equals,
00219 fn_not,
00220 fn_not_equals,
00221 fn_multiply,
00222 fn_divide,
00223 fn_div,
00224 fn_less_than,
00225 fn_greater_than,
00226 fn_greater_or_equal,
00227 fn_less_or_equal,
00228 fn_bit_and,
00229 fn_bit_or,
00230 fn_bit_not,
00231 fn_new_iterator,
00232 fn_length,
00233 fn_clone,
00234 fn_set_class,
00235 fn_add_array_slot,
00236 fn_stringer,
00237 fn_has_path,
00238 fn_classof
00239 };
00240
00242 static instruction_t is_instructions[] =
00243 {
00244 is_simple_instructions,
00245 is_dummy,
00246 is_dummy,
00247 is_push,
00248 is_push_constant,
00249 is_call,
00250 is_invoke,
00251 is_send,
00252 is_send_if_defined,
00253 is_resend,
00254 is_resend_if_defined,
00255 is_branch,
00256 is_branch_if_true,
00257 is_branch_if_false,
00258 is_find_var,
00259 is_get_var,
00260 is_make_frame,
00261 is_make_array,
00262 is_get_path,
00263 is_set_path,
00264 is_set_var,
00265 is_find_and_set_var,
00266 is_incr_var,
00267 is_branch_if_loop_not_done,
00268 is_freq_func,
00269 is_new_handlers
00270 };
00271
00273 static char * simple_instruction_names[] =
00274 {
00275 "pop",
00276 "dup",
00277 "return",
00278 "push-self",
00279 "set-lex-scope",
00280 "iter-next",
00281 "iter-done",
00282 "pop-handlers"
00283 };
00284
00286 static char * fn_instruction_names[] =
00287 {
00288 "add",
00289 "subtract",
00290 "aref",
00291 "set-aref",
00292 "equals",
00293 "not",
00294 "not-equals",
00295 "multiply",
00296 "divide",
00297 "div",
00298 "less-than",
00299 "greater-than",
00300 "greateror-equal",
00301 "lessor-equal",
00302 "bit-and",
00303 "bit-or",
00304 "bit-not",
00305 "new-iterator",
00306 "length",
00307 "clone",
00308 "set-class",
00309 "add-array-slot",
00310 "stringer",
00311 "has-path",
00312 "class-of"
00313 };
00314
00316 static char * vm_instruction_names[] =
00317 {
00318 "simple-instructions",
00319 NULL,
00320 NULL,
00321 "push",
00322 "push-constant",
00323 "call",
00324 "invoke",
00325 "send",
00326 "send-if-defined",
00327 "resend",
00328 "resend-if-defined",
00329 "branch",
00330 "branch-if-true",
00331 "branch-if-false",
00332 "find-var",
00333 "get-var",
00334 "make-frame",
00335 "make-array",
00336 "get-path",
00337 "set-path",
00338 "set-var",
00339 "find-and-set-var",
00340 "incr-var",
00341 "branch-if-loop-not-done",
00342 "freq-func",
00343 "new-handlers"
00344 };
00345
00346
00347 #pragma mark -
00348
00354 newtRef NVMSelf(void)
00355 {
00356 return RCVR;
00357 }
00358
00359
00360
00365 newtRef NVMCurrentFunction(void)
00366 {
00367 return FUNC;
00368 }
00369
00370
00371
00376 newtRef NVMCurrentImplementor(void)
00377 {
00378 return IMPL;
00379 }
00380
00381
00382
00391 bool NVMHasVar(newtRefArg name)
00392 {
00393 if (NewtHasLexical(LOCALS, name))
00394 return true;
00395
00396 if (NewtHasVariable(RCVR, name))
00397 return true;
00398
00399 if (NewtHasGlobalVar(name))
00400 return true;
00401
00402 return false;
00403 }
00404
00405
00406
00415 newtErr NVMGetExceptionErrCode(newtRefArg r, bool dump)
00416 {
00417 newtRefVar err;
00418
00419 if (NewtRefIsNIL(r))
00420 return kNErrNone;
00421
00422 if (dump)
00423 NewtPrintObject(stderr, r);
00424
00425 err = NcGetSlot(r, NSSYM0(error));
00426
00427 if (NewtRefIsNotNIL(err))
00428 return NewtRefToInteger(err);
00429
00430 return kNErrBadExceptionName;
00431 }
00432
00433
00434
00443 newtRef NVMMakeExceptionFrame(newtRefArg name, newtRefArg data)
00444 {
00445 newtRefVar r;
00446
00447 r = NcMakeFrame();
00448 NcSetSlot(r, NSSYM0(name), name);
00449
00450 if (NewtHasSubclass(name, NSSYM0(type.ref)))
00451 NcSetSlot(r, NSSYM0(data), data);
00452 else if (NewtHasSubclass(name, NSSYM0(ext.ex.msg)))
00453 NcSetSlot(r, NSSYM0(message), data);
00454 else
00455 NcSetSlot(r, NSSYM0(error), data);
00456
00457 return r;
00458 }
00459
00460
00461
00470 void NVMThrowData(newtRefArg name, newtRefArg data)
00471 {
00472 vm_excp_t * excp;
00473 uint32_t i;
00474
00475
00476 NVMClearCurrException();
00477
00478 CURREXCP = data;
00479
00480 for (i = EXCPSP; 0 < i; i--)
00481 {
00482 excp = &EXCPSTACK[i - 1];
00483
00484 if (NewtHasSubclass(name, excp->sym))
00485 {
00486 reg_rewind(excp->callsp);
00487 PC = excp->pc;
00488 return;
00489 }
00490 }
00491
00492 NVMNoStackFrameForReturn();
00493 }
00494
00495
00496
00505 void NVMThrow(newtRefArg name, newtRefArg data)
00506 {
00507 newtRefVar r;
00508
00509 r = NVMMakeExceptionFrame(name, data);
00510 NVMThrowData(name, r);
00511 }
00512
00513
00514
00520 void NVMRethrow(void)
00521 {
00522 if (NewtRefIsNotNIL(CURREXCP))
00523 {
00524 newtRefVar currexcp;
00525 newtRefVar name;
00526
00527 currexcp = CURREXCP;
00528 name = NcGetSlot(currexcp, NSSYM0(name));
00529
00530
00531 NVMThrowData(name, currexcp);
00532 }
00533 }
00534
00535
00536
00542 newtRef NVMCurrentException(void)
00543 {
00544 return CURREXCP;
00545 }
00546
00547
00548
00554 void NVMClearCurrException(void)
00555 {
00556 if (NewtRefIsNotNIL(CURREXCP))
00557 {
00558 excp_pop_handlers();
00559 CURREXCP = kNewtRefUnbind;
00560 }
00561 }
00562
00563
00564
00572 void NVMClearException(void)
00573 {
00574 CURREXCP = kNewtRefUnbind;
00575 }
00576
00577
00578 #pragma mark -
00579
00587 void NVMSetFn(newtRefArg fn)
00588 {
00589 FUNC = fn;
00590
00591 if (NewtRefIsNIL(FUNC) || ! NewtRefIsCodeBlock(FUNC))
00592 {
00593 BC = NULL;
00594 BCLEN = 0;
00595 }
00596 else
00597 {
00598 newtRefVar instr;
00599
00600 instr = NcGetSlot(FUNC, NSSYM0(instructions));
00601 BC = NewtRefToBinary(instr);
00602 BCLEN = NewtLength(instr);
00603 }
00604 }
00605
00606
00607
00613 void NVMNoStackFrameForReturn(void)
00614 {
00615 BC = NULL;
00616 BCLEN = 0;
00617 CALLSP = 0;
00618 }
00619
00620
00621 #pragma mark *** 呼出しスタック
00622
00630 void reg_rewind(int32_t sp)
00631 {
00632 if (sp == CALLSP)
00633 return;
00634
00635 if (sp < CALLSP)
00636 {
00637 CALLSP = sp;
00638 REG = CALLSTACK[CALLSP];
00639 NVMSetFn(FUNC);
00640 }
00641 else
00642 {
00643 NVMNoStackFrameForReturn();
00644 }
00645 }
00646
00647
00648
00654 void reg_pop(void)
00655 {
00656 reg_rewind(CALLSP - 1);
00657 }
00658
00659
00660
00668 void reg_push(int32_t sp)
00669 {
00670 if (! NewtStackExpand(&vm_env.callstack, CALLSP + 1))
00671 return;
00672
00673 CALLSTACK[CALLSP] = REG;
00674 CALLSTACK[CALLSP].sp = sp;
00675 CALLSP++;
00676 }
00677
00678
00679
00687 void reg_save(int32_t sp)
00688 {
00689
00690 reg_push(sp);
00691 }
00692
00693
00694 #pragma mark *** スタック
00695
00701 newtRef stk_pop0(void)
00702 {
00703 newtRefVar x = kNewtRefUnbind;
00704
00705 if (0 < SP)
00706 {
00707 SP--;
00708 x = STACK[SP];
00709 }
00710
00711 return x;
00712 }
00713
00714
00715
00721 newtRef stk_pop(void)
00722 {
00723 return NcResolveMagicPointer(stk_pop0());
00724 }
00725
00726
00727
00736 void stk_pop_n(int32_t n, newtRef a[])
00737 {
00738 for (n--; 0 <= n; n--)
00739 {
00740 a[n] = stk_pop();
00741 }
00742 }
00743
00744
00745
00751 void stk_remove(uint16_t n)
00752 {
00753 if (n < SP)
00754 SP -= n;
00755 else
00756 SP = 0;
00757 }
00758
00759
00760
00766 newtRef stk_top(void)
00767 {
00768 if (0 < SP)
00769 return STACK[SP - 1];
00770 else
00771 return kNewtRefNIL;
00772 }
00773
00774
00775
00783 void stk_push(newtRefArg value)
00784 {
00785 if (! NewtStackExpand(&vm_env.stack, SP + 1))
00786 return;
00787
00788 STACK[SP] = value;
00789 SP++;
00790 }
00791
00792
00793 #pragma mark *** 例外ハンドラスタック
00794
00804 bool excp_push(newtRefArg sym, newtRefArg pc)
00805 {
00806 vm_excp_t * excp;
00807
00808 if (! NewtRefIsSymbol(sym))
00809 return false;
00810
00811 if (! NewtRefIsInteger(pc))
00812 return false;
00813
00814 if (! NewtStackExpand(&vm_env.excpstack, EXCPSP + 1))
00815 return false;
00816
00817 excp = &EXCPSTACK[EXCPSP];
00818
00819 excp->callsp = CALLSP;
00820 excp->excppc = PC;
00821 excp->sym = sym;
00822 excp->pc = NewtRefToInteger(pc);
00823
00824 EXCPSP++;
00825
00826 return true;
00827 }
00828
00829
00835 void excp_pop(void)
00836 {
00837 if (0 < EXCPSP)
00838 EXCPSP--;
00839 }
00840
00841
00847 vm_excp_t * excp_top(void)
00848 {
00849 if (0 < EXCPSP)
00850 return &EXCPSTACK[EXCPSP - 1];
00851 else
00852 return NULL;
00853 }
00854
00855
00856
00862 void excp_pop_handlers(void)
00863 {
00864 vm_excp_t * excp;
00865
00866 excp = excp_top();
00867
00868 if (excp != NULL)
00869 {
00870 uint32_t excppc;
00871
00872 excppc = excp->excppc;
00873
00874 while (excp != NULL)
00875 {
00876 if (excp->excppc != excppc)
00877 break;
00878
00879 excp_pop();
00880 excp = excp_top();
00881 }
00882 }
00883 }
00884
00885
00886 #pragma mark *** Literals
00887
00895 newtRef liter_get(int16_t n)
00896 {
00897 newtRefVar literals;
00898
00899 literals = NcGetSlot(FUNC, NSSYM0(literals));
00900
00901 if (NewtRefIsNotNIL(literals))
00902 return NewtGetArraySlot(literals, n);
00903 else
00904 return kNewtRefNIL;
00905 }
00906
00907
00908 #pragma mark *** Iterator
00909
00918 newtRef iter_new(newtRefArg r, newtRefArg deeply)
00919 {
00920 newtRefVar iter;
00921
00922 iter = NewtMakeArray(NSSYM0(forEachState), kIterALength);
00923
00924 NewtSetArraySlot(iter, kIterObj, r);
00925
00926 if (NewtRefIsNIL(deeply))
00927 NewtSetArraySlot(iter, kIterDeeply, deeply);
00928 else
00929 NewtSetArraySlot(iter, kIterDeeply, NcDeeplyLength(r));
00930
00931 NewtSetArraySlot(iter, kIterPos, NSINT(-1));
00932 NewtSetArraySlot(iter, kIterMax, NcLength(r));
00933
00934 if (NewtRefIsFrame(r))
00935 NewtSetArraySlot(iter, kIterMap, NewtFrameMap(r));
00936 else
00937 NewtSetArraySlot(iter, kIterMap, kNewtRefNIL);
00938
00939 iter_next(iter);
00940
00941 return iter;
00942 }
00943
00944
00945
00953 void iter_next(newtRefArg iter)
00954 {
00955 newtRefVar deeply;
00956 newtRefVar obj;
00957 newtRefVar index = kNewtRefUnbind;
00958 newtRefVar value = kNewtRefUnbind;
00959 newtRefVar map;
00960 int32_t pos;
00961 int32_t len;
00962
00963 obj = NewtGetArraySlot(iter, kIterObj);
00964 deeply = NewtGetArraySlot(iter, kIterDeeply);
00965 pos = NewtRefToInteger(NewtGetArraySlot(iter, kIterPos));
00966 len = NewtRefToInteger(NewtGetArraySlot(iter, kIterMax));
00967 map = NewtGetArraySlot(iter, kIterMap);
00968
00969 if (NewtRefIsNIL(deeply) || NewtRefIsNIL(map))
00970 {
00971 pos++;
00972
00973 if (pos < len)
00974 {
00975 if (NewtRefIsNIL(map))
00976 {
00977 index = NewtMakeInteger(pos);
00978 value = NewtARef(obj, pos);
00979 }
00980 else
00981 {
00982 index = NewtGetArraySlot(map, pos + 1);
00983 value = NewtGetFrameSlot(obj, pos);
00984 }
00985 }
00986 }
00987 else
00988 {
00989 while (true)
00990 {
00991 pos++;
00992
00993 if (len <= pos)
00994 {
00995 obj = NcGetSlot(obj, NSSYM0(_proto));
00996
00997 if (NewtRefIsNIL(obj))
00998 {
00999 index = kNewtRefUnbind;
01000 break;
01001 }
01002
01003 map = NewtFrameMap(obj);
01004 len = NewtLength(obj);
01005
01006 NewtSetArraySlot(iter, kIterObj, obj);
01007 NewtSetArraySlot(iter, kIterMap, map);
01008 NewtSetArraySlot(iter, kIterMax, NewtMakeInteger(len));
01009
01010 pos = -1;
01011 continue;
01012 }
01013
01014 index = NewtGetArraySlot(map, pos + 1);
01015
01016 if (index != NSSYM0(_proto))
01017 {
01018 value = NewtGetFrameSlot(obj, pos);
01019 break;
01020 }
01021 }
01022 }
01023
01024 NewtSetArraySlot(iter, kIterIndex, index);
01025 NewtSetArraySlot(iter, kIterPos, NewtMakeInteger(pos));
01026 NewtSetArraySlot(iter, kIterValue, value);
01027 }
01028
01029
01030
01039 bool iter_done(newtRefArg iter)
01040 {
01041 int32_t pos;
01042 int32_t len;
01043
01044 pos = NewtRefToInteger(NewtGetArraySlot(iter, kIterPos));
01045 len = NewtRefToInteger(NewtGetArraySlot(iter, kIterMax));
01046
01047 return (len <= pos);
01048 }
01049
01050
01051 #pragma mark -
01052
01060 newtRef NVMMakeArgsArray(uint16_t numArgs)
01061 {
01062 newtRefVar args;
01063 int16_t i;
01064
01065 args = NewtMakeArray(kNewtRefUnbind, numArgs);
01066
01067 for (i = numArgs - 1; 0 <= i; i--)
01068 {
01069 NewtSetArraySlot(args, i, stk_pop());
01070 }
01071
01072 return args;
01073 }
01074
01075
01076
01084 void NVMBindArgs(uint16_t numArgs)
01085 {
01086 newtRefVar indefinite;
01087 int32_t minArgs;
01088 int16_t i;
01089 newtRefVar v;
01090
01091 minArgs = NewtRefToInteger(NcGetSlot(FUNC, NSSYM0(numArgs)));
01092 indefinite = NcGetSlot(FUNC, NSSYM0(indefinite));
01093
01094 if (NewtRefIsNotNIL(indefinite))
01095 {
01096 newtRefVar args;
01097
01098 args = NVMMakeArgsArray(numArgs - minArgs);
01099 NewtSetFrameSlot(LOCALS, START_LOCALARGS + minArgs, args);
01100 }
01101
01102 for (i = START_LOCALARGS + minArgs - 1; START_LOCALARGS <= i; i--)
01103 {
01104 v = stk_pop();
01105 NewtSetFrameSlot(LOCALS, i, v);
01106 }
01107 }
01108
01109
01110
01121 void NVMThrowBC(newtErr err, newtRefArg value, int16_t pop, bool push)
01122 {
01123 stk_remove(pop);
01124
01125 if (push)
01126 stk_push(kNewtRefUnbind);
01127
01128 if (NewtRefIsSymbol(value))
01129 NewtThrowSymbol(err, value);
01130 else
01131 NewtThrow(err, value);
01132 }
01133
01134
01135
01145 bool NVMFuncCheckNumArgs(newtRefArg fn, int16_t numArgs)
01146 {
01147 newtRefVar indefinite;
01148 int32_t minArgs;
01149
01150 minArgs = NewtRefToInteger(NcGetSlot(fn, NSSYM0(numArgs)));
01151 indefinite = NcGetSlot(fn, NSSYM0(indefinite));
01152
01153 if (NewtRefIsNIL(indefinite))
01154 return (minArgs == numArgs);
01155 else
01156 return (minArgs <= numArgs);
01157 }
01158
01159
01160
01169 newtErr NVMFuncCheck(newtRefArg fn, int16_t numArgs)
01170 {
01171
01172
01173 if (! NewtRefIsFunction(fn))
01174 return kNErrInvalidFunc;
01175
01176
01177
01178 if (! NVMFuncCheckNumArgs(fn, numArgs))
01179 return kNErrWrongNumberOfArgs;
01180
01181 return kNErrNone;
01182 }
01183
01184
01185
01194 void NVMCallNativeFn(newtRefArg fn, int16_t numArgs)
01195 {
01196 newtRefVar r = kNewtRefUnbind;
01197 newtRefVar indefinite;
01198 nvm_func_t funcPtr;
01199 int32_t minArgs;
01200
01201 funcPtr = (nvm_func_t)NewtRefToAddress(NcGetSlot(fn, NSSYM0(funcPtr)));
01202
01203 if (funcPtr == NULL)
01204 return;
01205
01206 minArgs = NewtRefToInteger(NcGetSlot(fn, NSSYM0(numArgs)));
01207 indefinite = NcGetSlot(fn, NSSYM0(indefinite));
01208
01209 if (NewtRefIsNIL(indefinite))
01210 {
01211 switch (minArgs)
01212 {
01213 case 0:
01214 r = (*funcPtr)();
01215 break;
01216
01217 case 1:
01218 {
01219 newtRefVar a;
01220
01221 a = stk_pop();
01222 r = (*funcPtr)(a);
01223 }
01224 break;
01225
01226 case 2:
01227 {
01228 newtRefVar a[2];
01229
01230 stk_pop_n(2, a);
01231 r = (*funcPtr)(a[0], a[1]);
01232 }
01233 break;
01234
01235 case 3:
01236 {
01237 newtRefVar a[3];
01238
01239 stk_pop_n(3, a);
01240 r = (*funcPtr)(a[0], a[1], a[2]);
01241 }
01242 break;
01243
01244 case 4:
01245 {
01246 newtRefVar a[4];
01247
01248 stk_pop_n(4, a);
01249 r = (*funcPtr)(a[0], a[1], a[2], a[3]);
01250 }
01251 break;
01252
01253 case 5:
01254 {
01255 newtRefVar a[5];
01256
01257 stk_pop_n(5, a);
01258 r = (*funcPtr)(a[0], a[1], a[2], a[3], a[4]);
01259 }
01260 break