@@ -279,8 +279,9 @@ const JOF = 17; // followed by: jump address
279279const GOTO = 18 ; // followed by: jump address
280280const LDF = 19 ; // followed by: max_stack_size, address, env extensn count
281281const CALL = 20 ;
282- const CALLP = 21 ;
282+ const CALLVAR = 21 ;
283283const LD = 22 ; // followed by: index of value in environment
284+ const LDV = 23 ;
284285const LDNULL = 26 ;
285286const RTN = 27 ;
286287const DONE = 28 ;
@@ -295,7 +296,7 @@ const primitives = list(
295296 list ( "IS_NUM " , 43 , is_number , "is_number" , list ( "any" ) , "bool" ) ,
296297 list ( "IS_PAIR" , 44 , is_pair , "is_pair" , list ( "any" ) , "bool" ) ,
297298 list ( "IS_NULL" , 45 , is_null , "is_null" , list ( "any" ) , "bool" ) ,
298- list ( "DISPLAY" , 46 , display , "display" , list ( "any " ) , "undefined" ) ,
299+ list ( "DISPLAY" , 46 , display , "display" , list ( "var " ) , "undefined" ) ,
299300 list ( "ERROR " , 47 , error , "error" , list ( "any" ) , "undefined" ) ,
300301 list ( "RANDOM " , 48 , math_random , "math_random" , null , "num" ) ,
301302 list ( "ABS " , 49 , math_abs , "math_abs" , list ( "num" ) , "num" ) ,
@@ -328,9 +329,13 @@ const primitives = list(
328329 list ( "TRUNC " , 76 , math_trunc , "math_trunc" , list ( "num" ) , "num" ) ,
329330 list ( "ATAN2 " , 77 , math_atan2 , "math_atan2" , list ( "num" , "num" ) , "num" ) ,
330331 list ( "IMUL " , 78 , math_imul , "math_imul" , list ( "num" , "num" ) , "num" ) ,
331- list ( "POW " , 79 , math_pow , "math_pow" , list ( "num" , "num" ) , "num" )
332- // list("MAX ", 66, math_max , "math_max" , list("var"), "num"),
333- // list("MIN ", 67, math_min , "math_min" , list("var"), "num")
332+ list ( "POW " , 79 , math_pow , "math_pow" , list ( "num" , "num" ) , "num" ) ,
333+ list ( "MAX " , 80 , math_max , "math_max" , list ( "var" ) , "num" ) ,
334+ list ( "MIN " , 81 , math_min , "math_min" , list ( "var" ) , "num" ) ,
335+ list ( "HYPOT " , 82 , math_hypot , "math_hypot" , list ( "var" ) , "num" ) ,
336+ list ( "RUNTIME" , 83 , runtime , "runtime" , null , "num" ) ,
337+ list ( "STRINGI" , 84 , stringify , "stringify" , list ( "num" ) , "str" )
338+ // list("PROMPT ", 84, prompt , "prompt" , null, "string")
334339) ;
335340
336341// auxiliary functions for injected primitive functions
@@ -362,6 +367,12 @@ function lookup_injected_prim_func_by_string(name) {
362367 }
363368 return lookup ( primitives ) ;
364369}
370+ function is_variadic_function ( name ) {
371+ // only checks injected primitive
372+ return is_injected_primitive ( name ) &&
373+ ! is_null ( member ( "var" ,
374+ injected_prim_func_ops_types ( lookup_injected_prim_func_by_string ( name ) ) ) ) ;
375+ }
365376// generate code snippet for primitive function
366377// to register them in the program
367378// takes on the form
@@ -423,8 +434,9 @@ const OPCODES = append(
423434 pair ( GOTO , "GOTO " ) ,
424435 pair ( LDF , "LDF " ) ,
425436 pair ( CALL , "CALL " ) ,
426- pair ( CALLP , "CALLP ") ,
437+ pair ( CALLVAR , "CALLVAR ") ,
427438 pair ( LD , "LD " ) ,
439+ pair ( LDV , "LDV " ) ,
428440 pair ( LDNULL , "LDNULL " ) ,
429441 pair ( RTN , "RTN " ) ,
430442 pair ( DONE , "DONE " )
@@ -711,7 +723,11 @@ function parse_and_compile(string) {
711723 index_table , false ) ;
712724 const max_stack_operands = compile_arguments ( operands ( expr ) ,
713725 index_table ) ;
714- add_unary_instruction ( CALL , length ( operands ( expr ) ) ) ;
726+ if ( is_variadic_function ( name_of_name ( operator ( expr ) ) ) ) {
727+ add_unary_instruction ( CALLVAR , length ( operands ( expr ) ) ) ;
728+ } else {
729+ add_unary_instruction ( CALL , length ( operands ( expr ) ) ) ;
730+ }
715731 return math_max ( max_stack_operator , max_stack_operands + 1 ) ;
716732 }
717733
@@ -775,8 +791,12 @@ function parse_and_compile(string) {
775791 const entry = lookup_injected_prim_func_by_string ( name ) ;
776792 const ops_types = injected_prim_func_ops_types ( entry ) ;
777793 const OP = injected_prim_func_opcode ( entry ) ;
778- for ( let i = length ( ops_types ) - 1 ; i >= 0 ; i = i - 1 ) {
779- add_unary_instruction ( LD , index_of ( index_table , "x" + stringify ( i ) ) ) ;
794+ if ( is_variadic_function ( name ) ) {
795+ add_nullary_instruction ( LDV ) ;
796+ } else {
797+ for ( let i = length ( ops_types ) - 1 ; i >= 0 ; i = i - 1 ) {
798+ add_unary_instruction ( LD , index_of ( index_table , "x" + stringify ( i ) ) ) ;
799+ }
780800 }
781801 add_nullary_instruction ( OP ) ;
782802 return 1 ;
@@ -860,7 +880,7 @@ function parse_and_compile(string) {
860880 }
861881
862882 // primitive functions according to source 2 specifications
863- // TODO: variadic functions: math_hypot, math_max, math_min, list etc.
883+ // TODO: variadic functions: math_hypot, list etc.
864884 const math_consts = "\
865885 const math_E = 2.718281828459045;\
866886 const math_LN10 = 2.302585092994046;\
@@ -1567,7 +1587,6 @@ M[TIMES] = () => { POP_OS();
15671587M [ EQUAL ] = ( ) => { POP_OS ( ) ;
15681588 A = HEAP [ RES + NUMBER_VALUE_SLOT ] ;
15691589 POP_OS ( ) ;
1570- show_registers ( "" ) ;
15711590 A = HEAP [ RES + NUMBER_VALUE_SLOT ] === A ;
15721591 NEW_BOOL ( ) ;
15731592 A = RES ;
@@ -1671,6 +1690,15 @@ M[LD] = () => { A = HEAP[ENV + HEAP[ENV + FIRST_CHILD_SLOT]
16711690 PC = PC + 2 ;
16721691 } ;
16731692
1693+ M [ LDV ] = ( ) => { E = HEAP [ OS + SIZE_SLOT ] - 4 ; // get the number of arguments
1694+ C = ENV + HEAP [ ENV + SIZE_SLOT ] - 1 ; // addr of last argument
1695+ for ( D = 0 ; D < E ; D = D + 1 ) {
1696+ A = HEAP [ C - D ] ;
1697+ PUSH_OS ( ) ;
1698+ }
1699+ PC = PC + 1 ;
1700+ } ;
1701+
16741702M [ CALL ] = ( ) => { G = P [ PC + 1 ] ; // lets keep number of arguments in G
16751703 // we peek down OS to get the closure
16761704 F = HEAP [ OS + HEAP [ OS + LAST_CHILD_SLOT ] - G ] ;
@@ -1700,35 +1728,34 @@ M[CALL] = () => { G = P[PC + 1]; // lets keep number of arguments in G
17001728 ENV = E ;
17011729 } ;
17021730
1703- // M[CALLP] = () => { G = P[PC + 1]; // lets keep number of arguments in G
1704- // H = P[PC + 2]; // keep the opcode to call in H
1705- // // we peek down OS to get the closure
1706- // F = HEAP[OS + HEAP[OS + LAST_CHILD_SLOT] - G];
1707- // // prep for EXTEND
1708- // A = HEAP[F + CLOSURE_ENV_SLOT];
1709- // // A is now env to be extended
1710- // H = HEAP[A + LAST_CHILD_SLOT];
1711- // // H is now offset of last child slot
1712- // B = HEAP[F + CLOSURE_ENV_EXTENSION_COUNT_SLOT];
1713- // // B is now the environment extension count
1714- // EXTEND(); // after this, RES is new env
1715- // E = RES;
1716- // H = E + H + G;
1717- // // H is now address where last argument goes in new env
1718- // for (C = H; C > H - G; C = C - 1) {
1719- // POP_OS(); // now RES has the address of the next arg
1720- // HEAP[C] = RES; // copy argument into new env
1721- // }
1722- // POP_OS(); // closure is on top of OS; pop it as not needed
1723- // NEW_RTS_FRAME(); // saves PC+2, ENV, OS
1724- // A = RES;
1725- // PUSH_RTS();
1726- // PC = HEAP[F + CLOSURE_ADDRESS_SLOT];
1727- // A = HEAP[F + CLOSURE_OS_SIZE_SLOT]; // closure stack size
1728- // NEW_OS(); // uses B and C
1729- // OS = RES;
1730- // ENV = E;
1731- // };
1731+ M [ CALLVAR ] = ( ) => { G = P [ PC + 1 ] ; // lets keep number of arguments in G
1732+ // we peek down OS to get the closure
1733+ F = HEAP [ OS + HEAP [ OS + LAST_CHILD_SLOT ] - G ] ;
1734+ // prep for EXTEND
1735+ A = HEAP [ F + CLOSURE_ENV_SLOT ] ;
1736+ // A is now env to be extended
1737+ H = HEAP [ A + LAST_CHILD_SLOT ] ;
1738+ // H is now offset of last child slot
1739+ B = HEAP [ F + CLOSURE_ENV_EXTENSION_COUNT_SLOT ] + G - 1 ;
1740+ // B is now the environment extension count
1741+ EXTEND ( ) ; // after this, RES is new env
1742+ E = RES ;
1743+ H = E + H + G ;
1744+ // H is now address where last argument goes in new env
1745+ for ( C = H ; C > H - G ; C = C - 1 ) {
1746+ POP_OS ( ) ; // now RES has the address of the next arg
1747+ HEAP [ C ] = RES ; // copy argument into new env
1748+ }
1749+ POP_OS ( ) ; // closure is on top of OS; pop it as not needed
1750+ NEW_RTS_FRAME ( ) ; // saves PC+2, ENV, OS
1751+ A = RES ;
1752+ PUSH_RTS ( ) ;
1753+ PC = HEAP [ F + CLOSURE_ADDRESS_SLOT ] ;
1754+ A = HEAP [ F + CLOSURE_OS_SIZE_SLOT ] + G - 1 ; // closure stack size
1755+ NEW_OS ( ) ; // uses B and C
1756+ OS = RES ;
1757+ ENV = E ;
1758+ } ;
17321759
17331760M [ LDNULL ] = ( ) => { NEW_NULL ( ) ;
17341761 A = RES ;
@@ -1758,7 +1785,7 @@ function insert_primitive(p) {
17581785 const ops_types = injected_prim_func_ops_types ( p ) ;
17591786 const rtn_type = injected_prim_func_return_type ( p ) ;
17601787 M [ OP ] = ( ) => {
1761- // gets arguments based on list of types
1788+ // handle special cases of primitives
17621789 if ( injected_prim_func_string ( p ) === "is_pair" ) {
17631790 POP_OS ( ) ; // get address of the node being tested
17641791 A = HEAP [ RES + TAG_SLOT ] === PAIR_TAG ;
@@ -1774,22 +1801,39 @@ function insert_primitive(p) {
17741801 POP_OS ( ) ;
17751802 RES = HEAP [ RES + TAIL_VALUE_SLOT ] ;
17761803 } else {
1777- const args =
1778- map ( x => {
1779- if ( x === "num" ) {
1780- POP_OS ( ) ; // get number node and extract value
1781- return HEAP [ RES + NUMBER_VALUE_SLOT ] ;
1782- } else if ( x === "addr" ) {
1783- POP_OS ( ) ; // get address of the node and return
1784- return RES ;
1785- } else { }
1786- } ,
1787- ops_types ) ;
1788- A = apply_in_underlying_javascript ( f , args ) ;
1804+ if ( is_variadic_function ( injected_prim_func_string ( p ) ) ) {
1805+ const num_of_args = HEAP [ OS + SIZE_SLOT ] - 4 ;
1806+ let args = null ;
1807+ for ( C = 0 ; C < num_of_args ; C = C + 1 ) {
1808+ POP_OS ( ) ;
1809+ args = pair ( HEAP [ RES + NUMBER_VALUE_SLOT ] , args ) ;
1810+ }
1811+ A = apply_in_underlying_javascript ( f , reverse ( args ) ) ;
1812+ } else {
1813+ // gets arguments based on list of types
1814+ const args =
1815+ map ( x => {
1816+ if ( x === "num" ) {
1817+ POP_OS ( ) ; // get number node and extract value
1818+ return HEAP [ RES + NUMBER_VALUE_SLOT ] ;
1819+ } else if ( x === "str" ) {
1820+ POP_OS ( ) ;
1821+ return HEAP [ RES + STRING_VALUE_SLOT ] ;
1822+ } else if ( x === "addr" ) {
1823+ POP_OS ( ) ; // get address of the node and return
1824+ return RES ;
1825+ } else {
1826+ }
1827+ } ,
1828+ ops_types ) ;
1829+ A = apply_in_underlying_javascript ( f , args ) ;
1830+ }
17891831 if ( rtn_type === "num" ) {
17901832 NEW_NUMBER ( ) ;
17911833 } else if ( rtn_type === "bool" ) {
17921834 NEW_BOOL ( ) ;
1835+ } else if ( rtn_type === "str" ) {
1836+ NEW_STRING ( ) ;
17931837 } else if ( rtn_type === "pair" ) {
17941838 B = tail ( A ) ;
17951839 A = head ( A ) ;
@@ -1866,8 +1910,8 @@ run();
18661910// run();
18671911
18681912P = parse_and_compile ( "\
1869- function foo() { return pair;} \
1870- foo()(1, 2); \
1913+ stringify(1000000000000000000000000000000000000000000000000000000); \
1914+ \
18711915" ) ;
18721916print_program ( P ) ;
18731917run ( ) ;
0 commit comments