66 applyFuncFactory ,
77 ARITHMETIC_OP_FX ,
88 ARITHMETIC_OP_TAG ,
9+ BOOL_NOT_FX ,
10+ BOOLISE_FX ,
911 COMPARISON_OP_FX ,
1012 COMPARISON_OP_TAG ,
1113 CURR_ENV ,
@@ -30,14 +32,15 @@ import {
3032 SET_PAIR_HEAD_FX ,
3133 SET_PAIR_TAIL_FX ,
3234 SET_PARAM_FX ,
35+ TYPE_TAG ,
3336} from "./constants" ;
3437import { f64 , global , i32 , i64 , local , mut , wasm } from "./wasm-util/builder" ;
35- import { WasmCall , WasmInstruction , WasmRaw } from "./wasm-util/types" ;
38+ import { WasmInstruction , WasmNumeric , WasmRaw } from "./wasm-util/types" ;
3639
3740const builtInFunctions : {
3841 name : string ;
3942 arity : number ;
40- body : WasmInstruction ;
43+ body : WasmInstruction | WasmInstruction [ ] ;
4144 isVoid : boolean ;
4245} [ ] = [
4346 {
@@ -97,22 +100,29 @@ const builtInFunctions: {
97100 ) ,
98101 isVoid : true ,
99102 } ,
103+ {
104+ name : "bool" ,
105+ arity : 1 ,
106+ body : [
107+ i32 . const ( TYPE_TAG . BOOL ) ,
108+ wasm
109+ . call ( BOOLISE_FX )
110+ . args ( wasm . call ( GET_LEX_ADDR_FX ) . args ( i32 . const ( 0 ) , i32 . const ( 0 ) ) ) ,
111+ ] ,
112+ isVoid : false ,
113+ } ,
100114] ;
101115
102116type Binding = { name : string ; tag : "local" | "nonlocal" } ;
103117
104- // all expressions compile to a call to a function like makeX, get/setLexAddress, arithOp, etc.
105- // so expressions return WasmCalls. (every expression results in i32 i64)
106- // WasmRaw is for function calls
107-
108118interface BuilderVisitor < S , E > extends StmtNS . Visitor < S > , ExprNS . Visitor < E > {
109119 visit ( stmt : StmtNS . Stmt ) : S ;
110120 visit ( stmt : ExprNS . Expr ) : E ;
111121 visit ( stmt : StmtNS . Stmt | ExprNS . Expr ) : S | E ;
112122}
113123
114124export class BuilderGenerator
115- implements BuilderVisitor < WasmInstruction , WasmCall | WasmRaw >
125+ implements BuilderVisitor < WasmInstruction , WasmNumeric >
116126{
117127 private strings : [ string , number ] [ ] = [ ] ;
118128 private heapPointer = 0 ;
@@ -186,8 +196,8 @@ export class BuilderGenerator
186196 }
187197
188198 visit ( stmt : StmtNS . Stmt ) : WasmInstruction ;
189- visit ( stmt : ExprNS . Expr ) : WasmCall | WasmRaw ;
190- visit ( stmt : StmtNS . Stmt | ExprNS . Expr ) : WasmInstruction | WasmCall | WasmRaw {
199+ visit ( stmt : ExprNS . Expr ) : WasmNumeric ;
200+ visit ( stmt : StmtNS . Stmt | ExprNS . Expr ) : WasmInstruction | WasmNumeric {
191201 return stmt . accept ( this ) ;
192202 }
193203
@@ -203,7 +213,7 @@ export class BuilderGenerator
203213 this . environment [ 0 ] . push ( { name, tag : "local" } ) ;
204214 const tag = this . userFunctions . length ;
205215 const newBody = [
206- body ,
216+ ... ( Array . isArray ( body ) ? body : [ body ] ) ,
207217 wasm . return (
208218 ...( isVoid ? [ wasm . call ( MAKE_NONE_FX ) ] : [ ] ) ,
209219 global . set ( CURR_ENV , local . get ( "$return_env" ) )
@@ -286,11 +296,11 @@ export class BuilderGenerator
286296 return wasm . drop ( wasm . drop ( expr ) ) ;
287297 }
288298
289- visitGroupingExpr ( expr : ExprNS . Grouping ) : WasmCall | WasmRaw {
299+ visitGroupingExpr ( expr : ExprNS . Grouping ) : WasmNumeric {
290300 return this . visit ( expr . expression ) ;
291301 }
292302
293- visitBinaryExpr ( expr : ExprNS . Binary ) : WasmCall {
303+ visitBinaryExpr ( expr : ExprNS . Binary ) : WasmNumeric {
294304 const left = this . visit ( expr . left ) ;
295305 const right = this . visit ( expr . right ) ;
296306
@@ -305,7 +315,7 @@ export class BuilderGenerator
305315 return wasm . call ( ARITHMETIC_OP_FX ) . args ( left , right , i32 . const ( opTag ) ) ;
306316 }
307317
308- visitCompareExpr ( expr : ExprNS . Compare ) : WasmCall {
318+ visitCompareExpr ( expr : ExprNS . Compare ) : WasmNumeric {
309319 const left = this . visit ( expr . left ) ;
310320 const right = this . visit ( expr . right ) ;
311321
@@ -322,17 +332,35 @@ export class BuilderGenerator
322332 return wasm . call ( COMPARISON_OP_FX ) . args ( left , right , i32 . const ( opTag ) ) ;
323333 }
324334
325- visitUnaryExpr ( expr : ExprNS . Unary ) : WasmCall {
335+ visitUnaryExpr ( expr : ExprNS . Unary ) : WasmNumeric {
326336 const right = this . visit ( expr . right ) ;
327337
328- if ( expr . operator . type !== TokenType . MINUS ) {
329- throw new Error ( `Unsupported unary operator: ${ expr . operator . type } ` ) ;
330- }
338+ const type = expr . operator . type ;
339+ if ( type === TokenType . MINUS ) return wasm . call ( NEG_FX ) . args ( right ) ;
340+ else if ( type === TokenType . NOT ) return wasm . call ( BOOL_NOT_FX ) . args ( right ) ;
341+ else throw new Error ( `Unsupported unary operator: ${ type } ` ) ;
342+ }
343+
344+ visitBoolOpExpr ( expr : ExprNS . BoolOp ) : WasmNumeric {
345+ const left = this . visit ( expr . left ) ;
346+ const right = this . visit ( expr . right ) ;
331347
332- return wasm . call ( NEG_FX ) . args ( right ) ;
348+ const type = expr . operator . type ;
349+
350+ const boolised = i64 . eqz ( wasm . call ( BOOLISE_FX ) . args ( left ) ) ;
351+
352+ if ( type === TokenType . AND ) {
353+ return wasm . raw `(if (result i32 i64) ${ boolised } (then ${ left } ) (else ${ right } ))` ;
354+ } else if ( type === TokenType . OR ) {
355+ return wasm . raw `(if (result i32 i64) ${ boolised } (then ${ right } ) (else ${ left } ))` ;
356+ } else throw new Error ( `Unsupported boolean binary operator: ${ type } ` ) ;
357+ }
358+
359+ visitNoneExpr ( expr : ExprNS . None ) : WasmNumeric {
360+ return wasm . call ( MAKE_NONE_FX ) ;
333361 }
334362
335- visitBigIntLiteralExpr ( expr : ExprNS . BigIntLiteral ) : WasmCall {
363+ visitBigIntLiteralExpr ( expr : ExprNS . BigIntLiteral ) : WasmNumeric {
336364 const value = BigInt ( expr . value ) ;
337365 const min = BigInt ( "-9223372036854775808" ) ; // -(2^63)
338366 const max = BigInt ( "9223372036854775807" ) ; // (2^63) - 1
@@ -343,7 +371,7 @@ export class BuilderGenerator
343371 return wasm . call ( MAKE_INT_FX ) . args ( i64 . const ( value ) ) ;
344372 }
345373
346- visitLiteralExpr ( expr : ExprNS . Literal ) : WasmCall {
374+ visitLiteralExpr ( expr : ExprNS . Literal ) : WasmNumeric {
347375 if ( typeof expr . value === "number" )
348376 return wasm . call ( MAKE_FLOAT_FX ) . args ( f64 . const ( expr . value ) ) ;
349377 else if ( typeof expr . value === "boolean" )
@@ -363,7 +391,7 @@ export class BuilderGenerator
363391 }
364392 }
365393
366- visitComplexExpr ( expr : ExprNS . Complex ) : WasmCall {
394+ visitComplexExpr ( expr : ExprNS . Complex ) : WasmNumeric {
367395 return wasm
368396 . call ( MAKE_COMPLEX_FX )
369397 . args ( f64 . const ( expr . value . real ) , f64 . const ( expr . value . imag ) ) ;
@@ -378,7 +406,7 @@ export class BuilderGenerator
378406 . args ( i32 . const ( depth ) , i32 . const ( index ) , expression ) ;
379407 }
380408
381- visitVariableExpr ( expr : ExprNS . Variable ) : WasmCall {
409+ visitVariableExpr ( expr : ExprNS . Variable ) : WasmNumeric {
382410 const [ depth , index ] = this . getLexAddress ( expr . name . lexeme ) ;
383411 return wasm . call ( GET_LEX_ADDR_FX ) . args ( i32 . const ( depth ) , i32 . const ( index ) ) ;
384412 }
@@ -437,8 +465,8 @@ export class BuilderGenerator
437465 // the SET_PARAM function returns the env address after setting the parameter
438466 // so we can chain the calls together
439467 return wasm . raw `
440- ( global.get ${ CURR_ENV } )
441- (call ${ PRE_APPLY_FX . name } ${ callee } ( i32.const ${ args . length } ))
468+ ${ global . get ( CURR_ENV ) }
469+ ${ wasm . call ( PRE_APPLY_FX ) . args ( callee , i32 . const ( args . length ) ) }
442470
443471${ args . map (
444472 ( arg , i ) =>
@@ -482,21 +510,14 @@ ${args.map(
482510 return wasm . nop ( ) ;
483511 }
484512
485- visitNoneExpr ( expr : ExprNS . None ) : WasmCall {
486- return wasm . call ( MAKE_NONE_FX ) ;
487- }
488-
489513 // UNIMPLEMENTED PYTHON CONSTRUCTS
490- visitBoolOpExpr ( expr : ExprNS . BoolOp ) : WasmCall {
491- throw new Error ( "Method not implemented." ) ;
492- }
493- visitTernaryExpr ( expr : ExprNS . Ternary ) : WasmCall {
514+ visitTernaryExpr ( expr : ExprNS . Ternary ) : WasmNumeric {
494515 throw new Error ( "Method not implemented." ) ;
495516 }
496- visitLambdaExpr ( expr : ExprNS . Lambda ) : WasmCall {
517+ visitLambdaExpr ( expr : ExprNS . Lambda ) : WasmNumeric {
497518 throw new Error ( "Method not implemented." ) ;
498519 }
499- visitMultiLambdaExpr ( expr : ExprNS . MultiLambda ) : WasmCall {
520+ visitMultiLambdaExpr ( expr : ExprNS . MultiLambda ) : WasmNumeric {
500521 throw new Error ( "Method not implemented." ) ;
501522 }
502523 visitIndentCreation ( stmt : StmtNS . Indent ) : WasmInstruction {
0 commit comments