From c64353fa9d2da4f279c0611586077fb1c3fe4039 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Thu, 15 Aug 2024 10:44:54 -0500 Subject: [PATCH] Fix "if" again when no else position. For JS, return null rather than undefined. For python, return null rather than error-ing out. --- index.html | 4 ++-- js/miniMAL-node.js | 2 +- js/step2_eval.js | 2 +- js/step3_env.js | 2 +- js/step4_if_fn_do.js | 2 +- js/step5_tco.js | 2 +- js/step6_file.js | 2 +- js/step7_interop.js | 2 +- js/step8_macros.js | 2 +- js/step9_try.js | 2 +- js/stepA_miniMAL.js | 2 +- js/stepB_node.js | 2 +- js/stepB_web.js | 2 +- js/web/miniMAL-min.js | 2 +- python/step4_if_fn_do.py | 2 +- python/step5_tco.py | 2 +- python/step6_file.py | 2 +- python/step7_interop.py | 2 +- python/step8_macros.py | 2 +- python/step9_try.py | 2 +- python/stepA_miniMAL.py | 2 +- tests/step4_if_fn_do.json | 4 ++-- 22 files changed, 24 insertions(+), 24 deletions(-) diff --git a/index.html b/index.html index 344d7b9..476ce08 100644 --- a/index.html +++ b/index.html @@ -32,8 +32,8 @@

A Delightfully Diminutive Lisp

- miniMAL:  min ( 829 bytes), - orig (4081 bytes, 119 lines)
+ miniMAL:  min ( 835 bytes), + orig (4089 bytes, 119 lines)
Core Lib: min (1086 bytes), orig (4161 bytes, 120 lines)
diff --git a/js/miniMAL-node.js b/js/miniMAL-node.js index 5b1eec7..afa7c95 100644 --- a/js/miniMAL-node.js +++ b/js/miniMAL-node.js @@ -1 +1 @@ -for(_='reZ[0]Y"==iY)XZturn WXWV){Ut,iTf(RRTQ]=QP[1]IeI,H)}G),E1).map(e=>Rt,e)ED.slice(Cr=iCDB[rrYI]JSON.ArrayiR");;elsei.at(-1)i= typeof ==i?i in ?t[ithrowObject.cZate((...eY:e)=> "  [2] eUWRs(t,H"assign(((e,r)=>parse()t=tEifunctionVBx=,module.exports=(nU s(T,nUW.some"&"==e+1]]=nCr):(t[e]=n],0)Et} Q,e,rUfor(;;UiR!.is(i))W""t]:n.(i+" not found"):{}&&keys(i).Zduce(eP]EeE{}):i;defVt[iIP ~VQIE{M:1}`ViI;.-2r?=r :x;.x.apply(rY,rC2)tryXtry{WQIGcatch([I],[e]E Gelse{fnViI,eEG,[i ,TI]letXI.mapr%2I-1]PI]):0EdoXiC1,-DifXi=QI)?i :i[3] iR(e=QY)).M)i=eiC1)){iRB!(0e))Wer);i=,t=s(He ,rG}}}Wn=nE{js:eval,eval Rn,E"= ===< <+ +- -* */ /H { },Zad ,slurp ZquiZ("fs").ZadFileSync(,"utf8"EZp stringify(Rn,)GG;';G=/[^ -AFJ-OS[-~]/.exec(_);)with(_.split(G))_=join(shift());eval(_) \ No newline at end of file +for(_='reZ[0]Y"==iY)XZturn WXWV){Ut,iTf(RRTQ]=QP[1]IeI,H)}G),E1).map(e=>Rt,e)ED.slice(Cr=iCDB[rrYI]JSON.ArrayiR");;elsei.at(-1)i= typeof ==i?i in ?t[ithrowObject.cZate((...eY:e)=> "  [2] eUWRs(t,H"assign(((e,r)=>parse()t=tEifunctionVBx=,module.exports=(nU s(T,nUW.some"&"==e+1]]=nCr):(t[e]=n],0)Et} Q,e,rUfor(;;UiR!.is(i))W""t]:n.(i+" not found"):{}&&keys(i).Zduce(eP]EeE{}):i??null;defVt[iIP ~VQIE{M:1}`ViI;.-2r?=r :x;.x.apply(rY,rC2)tryXtry{WQIGcatch([I],[e]E Gelse{fnViI,eEG,[i ,TI]letXI.mapr%2I-1]PI]):0EdoXiC1,-DifXi=QI)?i :i[3] iR(e=QY)).M)i=eiC1)){iRB!(0e))Wer);i=,t=s(He ,rG}}}Wn=nE{js:eval,eval Rn,E"= ===< <+ +- -* */ /H { },Zad ,slurp ZquiZ("fs").ZadFileSync(,"utf8"EZp stringify(Rn,)GG;';G=/[^ -AFJ-OS[-~]/.exec(_);)with(_.split(G))_=join(shift());eval(_) \ No newline at end of file diff --git a/js/step2_eval.js b/js/step2_eval.js index 5c2cba1..61320ff 100644 --- a/js/step2_eval.js +++ b/js/step2_eval.js @@ -11,7 +11,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : (a => {throw ast + " not found"})() // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step3_env.js b/js/step3_env.js index cbe0d23..159a50d 100644 --- a/js/step3_env.js +++ b/js/step3_env.js @@ -11,7 +11,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : (a => {throw ast + " not found"})() // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step4_if_fn_do.js b/js/step4_if_fn_do.js index a7b4d68..c5ff2c8 100644 --- a/js/step4_if_fn_do.js +++ b/js/step4_if_fn_do.js @@ -20,7 +20,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : (a => {throw ast + " not found"})() // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step5_tco.js b/js/step5_tco.js index 95446b3..d58d44a 100644 --- a/js/step5_tco.js +++ b/js/step5_tco.js @@ -21,7 +21,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : (a => {throw ast + " not found"})() // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step6_file.js b/js/step6_file.js index 645fcde..a43b8a1 100644 --- a/js/step6_file.js +++ b/js/step6_file.js @@ -21,7 +21,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : (a => {throw ast + " not found"})() // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step7_interop.js b/js/step7_interop.js index a88856e..f84855a 100644 --- a/js/step7_interop.js +++ b/js/step7_interop.js @@ -23,7 +23,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : E.throw(ast + " not found") // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step8_macros.js b/js/step8_macros.js index 5d77b8f..44d073e 100644 --- a/js/step8_macros.js +++ b/js/step8_macros.js @@ -23,7 +23,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : E.throw(ast + " not found") // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/step9_try.js b/js/step9_try.js index 7f47035..b344963 100644 --- a/js/step9_try.js +++ b/js/step9_try.js @@ -23,7 +23,7 @@ function EVAL(env, ast, f, el) { ? env[ast] // lookup symbol : E.throw(ast + " not found") // undefined symbol } else { - return ast + return ast ?? null } } else { // apply diff --git a/js/stepA_miniMAL.js b/js/stepA_miniMAL.js index d128942..1ca3e63 100644 --- a/js/stepA_miniMAL.js +++ b/js/stepA_miniMAL.js @@ -28,7 +28,7 @@ function EVAL(env, ast, f, el) { ? Object.keys(ast).reduce( (a,k) => (a[k] = EVAL(env, ast[k]), a), {}) // eval object values : ast // return ast unchanged - : ast + : ast ?? null } } else { // apply diff --git a/js/stepB_node.js b/js/stepB_node.js index 8fd23be..2947dc1 100644 --- a/js/stepB_node.js +++ b/js/stepB_node.js @@ -28,7 +28,7 @@ function EVAL(env, ast, f, el) { ? Object.keys(ast).reduce( (a,k) => (a[k] = EVAL(env, ast[k]), a), {}) // eval object values : ast // return ast unchanged - : ast + : ast ?? null } } else { // apply diff --git a/js/stepB_web.js b/js/stepB_web.js index 9561b81..0357ba2 100644 --- a/js/stepB_web.js +++ b/js/stepB_web.js @@ -28,7 +28,7 @@ function EVAL(env, ast, f, el) { ? Object.keys(ast).reduce( (a,k) => (a[k] = EVAL(env, ast[k]), a), {}) // eval object values : ast // return ast unchanged - : ast + : ast ?? null } } else { // apply diff --git a/js/web/miniMAL-min.js b/js/web/miniMAL-min.js index 72ecbaf..92906f0 100644 --- a/js/web/miniMAL-min.js +++ b/js/web/miniMAL-min.js @@ -1 +1 @@ -for(_='[0]5"==i5)4return Z4ZY){X(t,WaWiV]=VU[1]TeT,I)}H,rG),F1).map(e=>aWe)FE.slice(Dr=iDEC[rBr5BT]JSON.Arrayif(");;elsei.at(-1)i= typeof ==i?i in ?t[ithrowObject.create((...e5:e)=> "  [2] eXZa(sWI"assign(((eG)=>parse()t=tFifunctionYCA=,miniMAL=(nX sWi,nXZ.some"&"==eB+1]]=nDr):(t[e]=nB],0)Ft} V,eGXfor(;;X!.is(i))Z""t]:n.(i+" not found"):{}&&keys(i).reduce(eBUB]FeF{}):i;defYt[iTU ~YVTF{M:1}`YiT;.-2r?=r :A;.A.apply(r5GD2)try4try{ZVTHcatch([T],[e]F Helse{fnYiT,eFH,[i ,t,iT]let4T.mapr%2TB-1]UTB]):0Fdo4iD1,-Eif4i=VT)?i :i[3] (e=V5)).M)i=eiD1)){C!(0e))Zer);i=,t=s(Ie GH}}}Zn=n||thisF{js:eval,eval a(n,F"= ===< <+ +- -* */ /I { }Gead Gep stringify(a(n,)HH;';G=/[-B-IT-Z45]/.exec(_);)with(_.split(G))_=join(shift());eval(_) \ No newline at end of file +for(_='[0]5"==i5)4return Z4ZY){X(t,WaWiV]=VU[1]TeT,I)}H,rG),F1).map(e=>aWe)FE.slice(Dr=iDEC[rBr5BT]JSON.Arrayif(");;elsei.at(-1)i= typeof ==i?i in ?t[ithrowObject.create((...e5:e)=> "  [2] eXZa(sWI"assign(((eG)=>parse()t=tFifunctionYCA=,miniMAL=(nX sWi,nXZ.some"&"==eB+1]]=nDr):(t[e]=nB],0)Ft} V,eGXfor(;;X!.is(i))Z""t]:n.(i+" not found"):{}&&keys(i).reduce(eBUB]FeF{}):i??null;defYt[iTU ~YVTF{M:1}`YiT;.-2r?=r :A;.A.apply(r5GD2)try4try{ZVTHcatch([T],[e]F Helse{fnYiT,eFH,[i ,t,iT]let4T.mapr%2TB-1]UTB]):0Fdo4iD1,-Eif4i=VT)?i :i[3] (e=V5)).M)i=eiD1)){C!(0e))Zer);i=,t=s(Ie GH}}}Zn=n||thisF{js:eval,eval a(n,F"= ===< <+ +- -* */ /I { }Gead Gep stringify(a(n,)HH;';G=/[-B-IT-Z45]/.exec(_);)with(_.split(G))_=join(shift());eval(_) \ No newline at end of file diff --git a/python/step4_if_fn_do.py b/python/step4_if_fn_do.py index 97cf890..a818866 100755 --- a/python/step4_if_fn_do.py +++ b/python/step4_if_fn_do.py @@ -36,7 +36,7 @@ def EVAL(ast, env): elif "do" == ast[0]: return [EVAL(a, env) for a in ast[1:]][-1] elif "if" == ast[0]: - return EVAL(ast[2] if EVAL(ast[1], env) else ast[3], env) + return EVAL(ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0], env) elif "fn" == ast[0]: return lambda *a: EVAL(ast[2], Env(env, ast[1], a)) else: diff --git a/python/step5_tco.py b/python/step5_tco.py index 537a975..4004bed 100755 --- a/python/step5_tco.py +++ b/python/step5_tco.py @@ -38,7 +38,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/python/step6_file.py b/python/step6_file.py index ee8a298..5b95779 100755 --- a/python/step6_file.py +++ b/python/step6_file.py @@ -40,7 +40,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/python/step7_interop.py b/python/step7_interop.py index bb7a901..d562e45 100755 --- a/python/step7_interop.py +++ b/python/step7_interop.py @@ -45,7 +45,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/python/step8_macros.py b/python/step8_macros.py index b9e8ce5..88e2780 100755 --- a/python/step8_macros.py +++ b/python/step8_macros.py @@ -49,7 +49,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/python/step9_try.py b/python/step9_try.py index bef9ba0..a1c48cb 100755 --- a/python/step9_try.py +++ b/python/step9_try.py @@ -54,7 +54,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/python/stepA_miniMAL.py b/python/stepA_miniMAL.py index cc29b8e..486c6fd 100755 --- a/python/stepA_miniMAL.py +++ b/python/stepA_miniMAL.py @@ -55,7 +55,7 @@ def EVAL(ast, env): [EVAL(a, env) for a in ast[1:-1]] ast = ast[-1] # TCO elif "if" == ast[0]: - ast = ast[2] if EVAL(ast[1], env) else ast[3] # TCO + ast = ast[2] if EVAL(ast[1], env) else (*ast[3:4], None)[0] # TCO elif "fn" == ast[0]: fn = lambda *a: EVAL(ast[2], Env(env, ast[1], [*a])) fn.A = [ast[2], env, ast[1]] diff --git a/tests/step4_if_fn_do.json b/tests/step4_if_fn_do.json index 6f65e0a..079f8c0 100644 --- a/tests/step4_if_fn_do.json +++ b/tests/step4_if_fn_do.json @@ -29,8 +29,8 @@ ;=>false ["if", null, 8, 7] ;=>7 -["if", null, 8] -;=>undefined +["if", false, 8] +;=>null ;; Testing basic conditionals