cpu‿libpaths‿configs ← •args tab‿lf←@+9‿10 dig ← '0'+↕10 alph← "_"∾⥊"aA"+⌜↕26 wc ← dig∾alph∾"." # Word characters oc ← "!$%&*+-/<=>?\^|~" # Operator characters that can stick together # Source to list of token strings Tokenize←{ 𝕩+↩𝕩(=×lf⊸-)@+13 # Convert CR to LF 𝕩∾↩lf(≠⥊⊣)¯1↑𝕩 # Trailing newline # Resolve comments and strings s‿d‿c‿n←𝕩⊸=¨"'""#"∾lf⋄sd←/¨s‿d g←⍋q←(¯1↓¨sd)∾⊸∾/c ⋄q↩g⊏q # Open indices e← g⊏( 1↓¨sd)∾⊸∾-⟜»∘⊏⟜(0∾+`c)⊸//n∾1 # Matching close indices Se←≠(>/⊢)∾⟜≠{(⊏˜𝕨)𝕊⍟(≠○(¯1⊸⊑))𝕩∾𝕩⊏𝕨}⟨0⟩˙ # Find reachable openings a‿b←((≠𝕩)↑·/⁼(Se q⍋e)⊸⊏)¨q‿e # Open/close masks k←»≠`ab←a∨b # Token continuation mask {⟨⊑/𝕩,"Unclosed quote"⟩!0}⍟(∨´)(s∨d)>k∨a ign←(𝕩∊" "∾tab)∨≠`ab∧c∨n # Ignored characters # Other stuff da←(»𝕩='.')∧𝕩∊alph # Don't group ...word k∨↩da<∨´(»⊸∧k<𝕩⊸∊)¨wc‿oc # Group names, numbers, and ops bt←(⌈`↕∘≠׬)k ⋄ xd←𝕩∊dig k∨↩»⊸∨(»(bt⊏xd)∧𝕩='e')∧(𝕩='-')∧«xd # Negative exponents 12e-3 ts←n∨¬k∨ign # Token start mask lc←(1+/𝕩=lf){(⊢⋈¨𝕩-⊏⟜(0∾𝕨))𝕨⍋𝕩}/ts # Line/column numbers ⟨𝕩⊔˜1-˜(ign>≠`ab∧s∨d)¬⊸×+`ts, 𝕨 Source 𝕩‿lc⟩ } # Position handler for error reporting Source ← { 𝕨 𝕊 src‿lc: file←𝕨⊣"" { pos 𝕊 disp: r‿c←<˘⍉>pos⊏lc •Out ∾⟨file, ":", •Repr 1+e←¯1⊑r, ":"⟩ •Out src/˜(src=lf)(⊣<+`⊸=)e Tr ← { e ← (+`(𝕩≤¯1»𝕨≠⊸+¨𝕩))⊔𝕩⋈¨𝕨 l ← "^"⌾(1⊑¯1⊑⊑) ⌽ "|"⌾(1⊸⊑)¨⊸∾` (1+≠e)↑e {∾((-⟜»𝕨)∾≠¯1⊑𝕩)↑¨""<⊸∾𝕩}˝∘⍉∘>¨ l } •Out¨ disp Tr○((r=e)⊸/) c } } DispSource ← {𝕎𝕩}´ Err ← { (𝕩≠⊸⥊•Out‿DispSource) {𝕎𝕩}¨ 𝕩 ⋄ •Exit 1 } # Parameter checks for builtins (_p1 and _p2 to use BQN monad/dyad) _e1 ← {𝔽⊣"Expected one parameter" !1=≠} ⋄ _p1←{𝔽⊑_e1} _e2 ← {𝔽⊣"Expected two parameters"!2=≠} ⋄ _p2←{𝔽´_e2} _e3 ← {𝔽⊣"Expected three parameters"!3=≠} _v1 ← {𝔽⊣"Expected at least one parameter"!1≤≠} numbers ← {kname⇐"number" f ← •Import "float2.bqn" NN ← 1≠•Type # Not native number Is ← kname≡{Kind𝕩} Wrap ← {kind⇐kname⋄value⇐𝕩⋄Matches⇐Match⋄Shows⇐FmtLarge∘𝕩} Unwrap ← {6=•Type𝕩?kname≡𝕩.kind?𝕩.value; !"Expected constant number"} Promote ← NN◶f.To‿Unwrap From ⇐ f.From∘Unwrap⍟NN GetBool ⇐ {"Boolean expected"!⊑𝕩∊0‿1⋄𝕩}∘From Match ⇐ ∧○Is◶⟨0,≡○Promote⟩ _be ← {𝕗⊸×⊸+˜´⌽∘⊢} Nat ← (10 _be ⊣ "Ill-formed number"!·∧´0⊸≤∧≤⟜9) -⟜'0' LC ← +⟜(32×1="A["⊸⍋) '_'⊸≠⊸/ # Lowercase, underscores removed da ← dig∾'a'+↕26 Read ⇐ { (≠𝕩)>s←⌊´𝕩⊐"bx" ? # Base n with 0x9abc or 31bNUMBER b ← ('b'=s⊑𝕩)◶⟨16⊣·!"0"⊸≡,Nat⟩ s↑𝕩 "Invalid base" ! b≤≠da d ← (b↑da) (≠∘⊣(⊢⊣"Invalid digits"!∧´∘>)⊐) (1+s)↓𝕩 E←b _be ⋄ EE←{h‿l←f.To∘E¨𝕨-⊸(↓⋈↑)𝕩⋄Wrap l f.Add (f.To b⋆𝕨)f.Mul h} (⌊53÷2⋆⁼b) <⟜≠◶E‿EE d ; _n ← {('-'=⊑)◶⟨𝔽, -∘𝔽 1⊸↓⟩} Pos ← ⊐⟜"."⊸(Nat∘↑ + ·(0<≠)◶⟨0,Nat÷10⋆≠⟩+⟜1⊸↓) ⊐⟜"e"⊸(Pos _n∘↑ × <⟜≠◶⟨1,10⋆·Nat _n+⟜1⊸↓⟩) 𝕩 }⟜LC⎊{Err⟨•CurrentError@,𝕨⟩} InRange ← {1=⊑0⍋˜-˜´⟜(⌽𝕨)¨𝕩} FmtLarge ← { ⌊⊸≡𝕩 ? (f.Abs 𝕩) InRange 2⋆48‿64 ? "0x"∾da⊏˜⌽ 16‿16 f._repr 𝕩 ; FmtNum f.From 𝕩 } Cast ⇐ {'f'‿l𝕊n:1; q‿l𝕊n: # 1 if valid; error otherwise n NN◶⋈‿Unwrap↩ "Cannot cast float to integer"!⌊⊸≡n "Constant doesn't fit"!n InRange -⟜(1⊸⊑÷2˙)⍟(q='i') ⟨0,2⋆l⟩ } builtins ⇐ { W←Wrap ⋄ P←{𝕊:Promote𝕩 ; 𝕊⁼:W𝕩} ⋄ B←f.Bits∘P E←f.To 2⋆From pr‿val ← <˘⍉∘‿2⥊ ⟨ ⊢ ,⟨"neg",NN◶⟨-,W∘f.Neg○Unwrap⟩⟩‿⟨"not",¬GetBool⟩ {𝕏⌾P} ,⟨"add"‿f.Add, "sub"‿f.Sub, "mul"‿f.Mul, "div"‿f.Div, "mod"‿f.Mod⟩ {W P⊸𝕏⟜E},⟨"shl", f.Mul⟩‿⟨"shr", f.Floor f.Div⟩ {𝕏⌾B} ,⟨ "and"‿∧, "or"‿∨, "xor"‿≠ ⟩ ⟩ arg ← 1‿3/{𝕏_p1}‿{𝕏_p2} ⍉>∾ (arg {𝕎∘𝕏}¨ {{𝕏⚇0}∘𝕏⚇0}¨ pr) {⟨"__"⊸∾,𝕎⟩⊸({𝕎𝕩}¨)¨𝕩}¨ val } _cmp ⇐ {(f.Cmp 𝔽 0˙)○Promote} } ptrWidth ← cpu.width architecture ← { feats‿mat‿FeatInd ← cpu init ⇐ cpu.baseArch # Look up a list of symbols Id ← {𝕨 FeatInd "Expected symbol for architecture feature"⊸symbols.From¨𝕩} # An architecture is a mask of supported features New ⇐ { 𝕨 ∨˝ (1 Id 𝕩) ⊏ mat } Contains ⇐ ∧´≥ Intersect ⇐ ∧ ⋄ Union ⇐ ∨ Has ⇐ ∧´{(0 Id 𝕩)⊏𝕨∾0} # Has all in list 𝕩 List ⇐ /⟜feats ListExt ⇐ List init⊸< # Architecture to be used for the next function created next ← init SeeNext ⇐ {𝕊:next} NewFunction ⇐ {𝕊: r←next ⋄ next↩init ⋄ r } With ⇐ { NewFunction ⊢ (⊑𝕩){𝔽} ⊣ {next↩𝕩}∘(New 1↓𝕩) }_v1 } MakeStack ← {𝕤 st←@ ⋄ d←0 Push⇐{ st↩𝕩‿st ⋄ d+↩1} Pop ⇐{𝕤⋄ r‿s←st ⋄ st↩s ⋄ d-↩1 ⋄ r} Arr ⇐{𝕤⋄ ⊑¨ ⌽ 1⊸⊑⍟(↕d) st} _while_⇐{Pop ⊢ 𝔽 ⊣ ·Push𝕘˙} } MakeStream ← { len←≠src←𝕩 ⋄ i←0 Pos ⇐ {𝕤⋄i} Inc ← {𝕤⋄i+↩1} Rem ⇐ {𝕤⋄iDumpStack@ •Out "" F ← (⥊lf)⊸≡◶•Repr‿"end of line" •Out {∾"Expected "‿𝕨‿" but saw "‿𝕩}⟜F´⍟(1<≡) 𝕨 •Exit 1 } MakeTokStream ← { i←⊐𝕩 ⋄ u←𝕩/˜i>¯1»⌈`i ⟨Inc⇐Next,PeekRaw⇐Peek⟩←⟨Pos,Rem,Back⇐Dec⟩⇐MakeStream i PeekRaw ↩ PeekRaw ⊣ "File ended unexpectedly" Asrt Rem Peek ← ⊑⟜u∘PeekRaw Try ⇐ 1∘Inc⍟⊢ Peek⊸≡ Get ⇐ Inc (•Repr⊸⋈ Asrt 0˙)⍟≢⟜Peek # Faster tests on raw tokens _test ⇐ {(𝔽¨u)⊑˜PeekRaw} first←⊑¨u _begin_ ⇐ {t←𝔽 first ⋄ Inc ⊢ (⊑⟜u (⊣ ⊣ 𝕘⊸⋈⊸Asrt) ⊑⟜t)∘PeekRaw} GetS ← ⊢ {Inc (((•Repr𝕨)⋈⊑⟜u) Asrt 0˙)⍟(𝕩⊸≢)∘PeekRaw}¨ u⊸⊐ _seq ⇐ {a←0=•Type¨𝕗 ⋄ (¬a)/{𝕏@}¨∘(GetS⌾(a⊸/)𝕗) } _opt_ ⇐ {@_𝕣_𝕘: t‿c ← (1⌾(¯1⊸⊑)2|↕∘≠)⊸⊔ 𝕘 exp ← "one of "∾∾⟜", "⊸∾´•Repr¨t (⊑(u⊐t)⊐PeekRaw)◶(c∾⟨(exp⋈Peek) Asrt 0˙⟩) } _optGet_ ⇐ {@_opt_({𝕏⊣Inc}¨⌾((2|↕∘≠𝕘)⊸/)𝕘)} _any ⇐ {⊑(u⊐𝕗)∊˜PeekRaw} _anyTry ⇐ {1∘Inc⍟⊢∘(𝕗_any)} } ⟨Get,Try,Rem,Pos,Back,_test,_begin_,_seq,_opt_,_optGet_,_anyTry,_any⟩ ← MakeTokStream tokens # Node creation and error tracking c ← nodes ⟨_whileParse_⇐_while_, DumpStack⇐Arr⟩ ← MakeStack@ _node_ ← {p←Pos@ ⋄ (ShowTrace○⋈⟜""⊢)‿p 𝔽 𝔾_whileParse_⟨p,𝕗⟩ 𝕩} When ← {Test‿Cont: ( ⥊∘< Cont)⍟Test ⟨⟩ } While ← {Test‿Cont‿init: {(𝕊∾⟜<⟜Cont)⍟Test𝕩} Cont¨↕init} _ifASCII ← {(@+128)⊸≤∨𝔽} Name ← ∊⟜alph _begin_ "name" Oper ← ∊⟜oc _ifASCII _begin_ "operator" Symbol ← c.symbol _node_ ('''⊸=_begin_"symbol") IsLogic ← ∊⟜"and"‿"or"‿"not"⌾< LFs ← {𝕊⍟Try ⟨lf⟩} Div ← {LFs@ ⋄ 1∘LFs⍟⊢ Try 𝕩} # Divider, allowing surrounding newlines TrySep ← sep _anyTry Seps ← {Rem@ ? TrySep@ ? 𝕊𝕩⋄1 ; 0} _decl_ ← { 𝔽"Declaration" ⋄ Declare 𝔾 𝕩 } _exprStmt ← {AsrtStmt _𝕣: @_opt_⟨ "if", { StIf 𝕩 } "while", { StWhile 𝕩 } "do", { DoWhile 𝕩 } "@", { For 𝕩 } "extend", { Extend 𝕩 } "def", { Define 𝕩 } ⊣ AsrtStmt "fn", { DefFun 𝕩 } ⊣ AsrtStmt "oper", { OpDef 𝕩 } ⊣ AsrtStmt "{", @_optGet_⟨"=>", c.lambda _node_ (⋈⟜{Block𝕩}) ":", AsrtStmt _decl_ ⊢ ⟩ {Params𝕩} { AsrtStmt _decl_ ToId⍟(Try":") SimpExpr 𝕩 } ⟩} Expr ← (∾⟜" must appear on its own line" Asrt 0˙) _exprStmt Stmt ← ⊢ _exprStmt Vec ← c.run _node_ (c.word∘"__vec" ⋈ "["‿Expr‿"]"‿{Expr0𝕩} _seq) Par ← ⊑ "("‿Expr‿")" _seq EW ← ('''≠⊑)◶⟨c.symbol,(⊑⊏∊dig˙)◶c.word‿c.number⟩ EWord ← EW ∊⟜('''∾wc∾oc)_ifASCII _begin_ "expression" Expr0 ← @_opt_⟨"[",Vec, "(",Par, EWord⟩ _spreadable ← {<∘⊢⍟⊣⟜𝔽∘Try∘"..."} _args ← {𝕗 _argsFn_ (Expr _spreadable)} _argsFn_ ← {𝕤 Get ⊑𝕗 Try 1⊑𝕗 ? ⟨⟩ ; LFs@ a ← While ⟨Div∘",", 𝔾, 1⟩ Get 1⊑𝕗 a } AddParams ← @_opt_⟨"{", {AddParams∘(c.run _node_ (⊢⋈"{"‿"}"_args)) 𝕩}, ⊢⟩ AddArgs ← @_opt_⟨"(", { (c.call _node_ (⊢⋈"("‿")"_args)) 𝕩}, ⊢⟩ Callable ← AddParams∘Expr0 CanCall ← (¬IsLogic∨´(oc∾"[")=⊏) _test StartsOp ← (IsLogic ∨ ·⊑∊⟜oc _ifASCII∘⊑) _test Call ← { c←CanCall @ ⋄ AddArgs⍟c Callable𝕩 } ExprFromEnd ← {𝕊 endTok: End ← (endTok∾sep∾⥊¨",:)}]")_any { o ← StartsOp 𝕩 Cont ← {p←o ⋄ p∨o↩StartsOp 𝕩}_and_(¬End) c.phrase _node_ (While∘⟨Cont, Call, 1⟩) 𝕩 } } SimpExpr‿TypeExpr‿CondExpr ← ExprFromEnd¨ ⟨⟩‿⟨"="⟩‿⟨"&"⟩ # 𝕩 is the expression preceding ":" Declare ← c.declare _node_ { n ← 𝕩 t ← When ⟨¬Try"=", Get∘"=" ⊢ TypeExpr⟩ ⟨n,t,Expr@⟩ } ToId ← {𝕩.IsDef@⋄𝕩} c.PhraseTryWord _lines_ ← { Line _𝕣_ Cont 𝕩: Seps @ ⋄ s ← 1 SepLine ← {"Expected separator" Asrt s ⋄ l←Line𝕩 ⋄ s↩Seps@ ⋄ l} While ⟨Cont, SepLine, 0⟩ } _blockLines ← { ⊑ ⟨"{", 𝔽 _lines_ (¬Try∘"}")⟩_seq } Body ← Stmt _blockLines Block ← @_opt_⟨"{",c.body _node_ Body, Expr⟩ _if ← { TrySeps ← {s←Seps@ ⋄ Back⊸⊢⍟(s>⊢) Try 𝕩} "if"‿"("‿Expr‿")"‿𝔽‿(When∘⟨TrySeps∘"else",𝔽⟩)_seq } StIf ← c.if _node_ (Block _if) StWhile ← c.while _node_ (1 ∾ "while"‿"("‿Expr‿")"‿Block _seq) DoWhile ← c.while _node_ (0 ∾⟜⌽ "do"‿Block‿"while"‿"("‿Expr‿")" _seq) For ← c.for _node_ {𝕤 OA← "@for: multiple variables must use ""over"""⊸Asrt TA← "@for: ""from"" missing ""to"""⊸Asrt NA← "@for: loop variable must be a name"⊸Asrt Get "@" f ← Callable@ Get "(" to← SimpExpr@ NE← {𝕤⋄ n←⋈∘{NA@≢𝕩⋄𝕩}∘c.PhraseTryName⍟𝕩 to ⋄ to↩SimpExpr@ ⋄ n} {Try"in"? to↩⟨⊑NE 1,to⟩; @} pe← While ⟨Try∘",", Try∘"in"◶⟨⋈,⋈⟜SimpExpr⟩ Name, 0⟩ ps← {Try"over"?() T ⇐ (p C {𝕩.bind}){{⊣AC𝕏}⍟a𝕗} } tabs ⇐ nul‿lef ← parent.tabs Tab¨ ⟨ {𝕨𝕊⟨value, prec⟩: null ⇐ 𝕨 Op ⟨value, prec, <, 0⟩ } {𝕨𝕊⟨value, prec, assoc⟩: bind ⇐ prec left ⇐ 𝕨 Op ⟨value, prec, ("lrn"⊸⊐⌾"‿𝕩}⟜Show´ # Function: ⟨q‿r‿s, t⟩ (…,…,…) -> … T # Tuple: q‿r‿s (…,…,…) ⟩∘dat Matches⇐{𝕨Is∘⊢◶0‿Equiv𝕩} } tVOID‿tPRIM‿tVEC‿tPTR‿tFUN‿tTUP ← ↕6 TypeKind⇐{ "typekind argument must be type"!Is 𝕩 𝕩.typeKind⊑"void"‿"primitive"‿"vector"‿"pointer"‿"function"‿"tuple" } IsVoid ⇐ {tVOID≡𝕩.typeKind} primTypes ⇐ (tVOID New ⟨⟩) ∾ tPRIM New¨ qw ← ∾⋈¨¨˝⍉ ∘‿2⥊⟨ 'u', 2⋆0∾3+↕4 # 1/8/16/32/64 'i', 2⋆ 3+↕4 # 8/16/32/64 'f', 2⋆ 5+↕2 # 32/64 ⟩ _getPrim ← {{𝕏@} (⟨!∘𝕗⟩«primTypes) ⊑˜ qw⊸⊐⌾<} Is ⇐ kname≡Kind Vec ← {n𝕊t: "Vector size should be a constant integer"!IsNat n ⋄ !Is t ⋄ tVEC New ⟨n,t⟩} Ptr ← { 𝕊t: "Pointer type wasn't type"!Is t ⋄ tPTR New t} Tup ⇐ { 𝕊t: !IsTup t ⋄ !∧´Is¨ t ⋄ tTUP New t} Fun ⇐ tFUN New ⋈ _get⇐ {IsTup 𝕩 ? Tup 𝕊¨𝕩 ; !∘(𝕗∾" type must be a type"˙)⍟(¬Is) 𝕩} _cases ← { Kind←{𝕩.typeKind} ⋄ Dat←{𝕩.dat} c ← ⌊‿2⥊𝕗 k ← ⊏˘c d ← (1⊏˘c) ∾ ((≠⥊c)↓𝕗)»⟨!∘0⟩ (k⊸⊐⌾< ⊢⊘(≠◶⊢‿¯1)○Kind)◶({𝕏○Dat}¨⌾((≠k)⊸↑)d) ⊣ @○(!Is) } Quality ← ⟨tPRIM,{symbols.New ⋈⊑𝕩}, !∘"Non-primitive type"⟩_cases _isQual ← {⟨tPRIM,𝔽⊑,0⟩_cases TypeOf⍟(¬Is)} Unpack ⇐ ⟨tTUP,{Unpack¨𝕩},⊢⟩_cases Ungather ⇐ ⟨tTUP,⊢,!∘"Gathered argument must have a tuple type"⟩_cases Deref ⇐ { Is 𝕩 ? tPTR=𝕩.typeKind ? 𝕩.dat ; !"Expected pointer" } Width ← ⟨ tPRIM, 1⊸⊑ tVEC, ×⟜{Width𝕩}´ tTUP, +´{Width𝕩}¨ tPTR, ptrWidth {!∾⟨"Can't find width of ",TypeKind𝕩," types"⟩} ⟩_cases VCount ← ⟨ tVEC,⊑, 1 ⟩ _cases VType ← ⟨ tVEC,1⊸⊑, tPTR,⊢ ⟩ _cases FnCast ⇐ { args‿ret ← ⟨tFUN,⊢, !∘"Calling non-function"⟩_cases 𝕨 args(("Wrong number of arguments: expected "∾•Repr∘⊣)!≡)○≠𝕩 ⟨args Cast¨ 𝕩, ret⟩ } _typeRel_ ← { 𝕨 ⟨ tVOID, 1 tPRIM, 𝔽 tVEC, =○⊑ _and_ (𝕊○(¯1⊸⊑)) tPTR, (@≢𝕘)⊑𝕊‿𝕘 tTUP, MTup ← =○≠ _and_ (∧´𝕊¨) tFUN, 𝕊○(1⊸⊑) _and_ (MTup○⊑) 0 ⟩ _cases 𝕩 } _cmpPrim ← { L←¯1⊸⊑ ⋄ ≠○⊑◶⟨𝔽○L, ('f'≠⊑∘⊣)_and_(<○L)⟩ } Equiv ← ≡ _typeRel_ @ Subtype ⇐ ≤ _cmpPrim _typeRel_ 1 SSubtype ⇐ < _cmpPrim _typeRel_ 0 _asCast ← { "Can't cast to non-type"!Is𝕨 Fail ← {!∾⟨"Can't cast ",Kind𝕩," to ",Show𝕨⟩} Num ← {t𝕊n: ⟨ tPRIM,numbers.Cast⟜n, Fail⟜n ⟩ _cases t t constants.New n } Cast ← 𝕊 Tup ← { ptr ← 0 c ← ⟨ tTUP,⊢, tPTR,{ptr↩1⋄𝕩}, Fail⟜𝕩 ⟩_cases⍟(0≠•Type) 𝕨 𝕨 functions.Array⍟ptr c Cast¨ 𝕩 } Obj ← ("number"≢{𝕩.kind})◶⟨Num,IsTyped∘⊢◶⟨Fail˜,𝔽⟩⟩ # _tsel selects on 𝕨; swap to use 𝕩 𝕨 ⟨Tup˜, Num˜, Fail˜, Fail˜, Obj˜⟩_tsel˜ 𝕩 } _cc ← { Test‿Conv‿Fail _𝕣: (Conv ⊣ Fail○Show⍟(¬Test˜)⟜TypeOf)_asCast } Cast ⇐ ⟨ Equiv, ⊢ {!∾⟨"Explicit conversion required to change ",𝕩," to ",𝕨⟩} ⟩_cc Promote ← ⟨ Subtype, {functions.Emit⟨𝕨, symbols.New "^promote", 𝕨, 𝕩⟩} {!∾⟨"Can't promote from type ",𝕩," to non-subset ",𝕨⟩} ⟩_cc Reinterpret ← ⟨ ≡○Width, {functions.Emit⟨𝕨, symbols.New "^promote", 𝕨, 𝕩⟩} {!∾⟨"Can't reinterpret type ",𝕩," as different-width type ",𝕨⟩} ⟩_cc IncWidth ← { "First parameter of promote must be a type or number"!"number"≡Kind𝕨 n←numbers.From 𝕨 t←TypeOf 𝕩 (1 + n ×∘- Width t)◶⟨ !∘"Can't decrease width in promotion" ⊢ ⟨ tPRIM, "Invalid width"_getPrim 𝕨⌾(1⊸⊑) !∘"Can't increase width of non-primitive type" ⟩_cases∘t⊸Promote ⟩ 𝕩 } GetQual ← { e ← "Quality must be a single-letter symbol (i,u,f)" n ← e symbols.From 𝕩 ⋄ e!1=≠n ⊑n } PrimType ← "Invalid primitive type specification"_getPrim ⟨GetQual,numbers.From⟩ {𝕎𝕩}¨ ⊢ builtins ⇐ ∾˘⍉∘‿2⥊⟨ ⟨"cast" , "promote" ,"reinterpret"⟩ ⟨ Cast _p2,Is∘⊣◶IncWidth‿Promote _p2, Reinterpret _p2⟩ ⟨"eltype" ,"vcount" ,"width" , "__vec" ,"__pnt"⟩ ⟨ VType _p1 , VCount _p1, Width _p1,numbers.From⊸Vec _p2, Ptr _p1⟩ ⟨"primtype" ,"quality","isfloat","issigned","isint"⟩ ⟨ PrimType _e2, Quality _p1⟩∾{𝕩_isQual _p1}¨⟨'f'⊸≡ ⋄ 'i'⊸≡ ⋄ ⊑∘∊⟜"iu"⟩ ⟩ } registers ← {kname⇐"register" Is ← kname ≡ Kind Transient ⇐ { owner⇐functions.current kind⇐kname ⋄ shows⇐"(temp)" ⋄ type⇐𝕩 ⋄ fmtType⇐1 ⋄ Matches⇐≡ name←⟨⟩ ⋄ AddName⇐{name∾↩<𝕩} mut⇐0 ⋄ ref⇐0 ⋄ Use⇐{𝕤⋄ref+↩1} ⋄ SetMut⇐! ShowReg⇐{showReg↩∾⟨𝕏@⟩∾"_"⊸∾¨(ref=1)/name} } Declare ⇐ { name 𝕊 type‿val: owner⇐functions.current kind⇐kname ⋄ shows⇐name ⋄ type⇐ ⋄ fmtType⇐1 ⋄ Matches⇐≡ addName⇐@ ⋄ {𝕩.AddName name}⍟Is val mut⇐0 ⋄ ref⇐0 ⋄ Use⇐{𝕤⋄ref+↩1} SetMut⇐{𝕤⋄mut↩1} # Changed (for blocks, and transient elimination) ShowReg⇐{showReg↩𝕩}∘{ Is val? ¬val.mut? (¬mut)∨1=val.ref? ref+↩val.ref-1 ⋄ val.ShowReg𝕩 ; ∾⟨𝕏@,"_",name⟩ } } Mutable ⇐ { Is 𝕩 ? {!}≢𝕩.setMut ; 0 } Mutated ⇐ { Is 𝕩 ? 𝕩.mut ; 0 } MarkUse ⇐ {𝕩.Use@}⍟Is CheckAppend ⇐ { "Register used outside its owning function"!𝕨≡𝕩.owner }⍟(Is⊢) } constants ← {kname⇐"constant" New ⇐ { kind⇐kname ⋄ type⇐𝕨 ⋄ value⇐𝕩 shows⇐∾"!:"∾¨Show¨𝕩‿𝕨 ⋄ fmtType⇐0 ⋄ Matches⇐≡ } Static ⇐ { kind⇐kname ⋄ type‿handle⇐𝕩 shows⇐"$c"∾(""⊢"_"∾𝕨)∾˜•Repr handle ⋄ fmtType⇐1 ⋄ Matches⇐≡ } Undefined ⇐ { kind⇐kname ⋄ shows⇐"?:"∾Show type⇐𝕩 ⋄ fmtType⇐0 ⋄ Matches⇐≡ } Exportable ⇐ (kname‿"function"⊸⊐⌾< Kind)◶{"?:"≢2↑𝕩.shows}‿1‿0 } labels ← {kname⇐"label" New ⇐ { kind⇐kname ⋄ shows⇐"l"∾•Repr𝕩 ⋄ Matches⇐≡ } } symbols ← {kname⇐"symbol" Is ← kname ≡ Kind From ⇐ {!⟜(Is𝕩˙)𝕨 ⋄ 𝕩.symstr} M ← Is∘⊢_and_(≡○From) Enc ← "'"(∾∾⊣)⊢+128×' '⊸= # Space to non-breaking space New ⇐ { kind⇐kname ⋄ symstr⇐𝕩 ⋄ Shows⇐Enc∘symstr ⋄ Matches⇐M } } functions ← {kname⇐"function" current⇐nofn←{ Append⇐NextLabel⇐Return⇐SetArch⇐!∘"No function active" arch ⇐ architecture.init } New ← {𝕤 kind⇐kname ⋄ shows⇐"$f"∾(•Repr id⇐𝕩)∾"_"⊸∾⍟(0<≠)𝕨 ⋄ Matches⇐≡ ⋄ type⇐@ arch⇐architecture.NewFunction@ ⋄ SetArch⇐{arch↩𝕩} label←¯1 ⋄ slabel←⟨⟩ ⋄ args←atypes←ctypes←⟨⟩ ⋄ rType⇐@ NextLabel⇐{𝕤⋄ labels.New label+↩1 } UseSymLabel⇐{ ∊⟜slabel⌾<𝕩 ? !∾"Label "‿𝕩‿" used in this function already" ; slabel∾↩<𝕩 ⋄ 𝕩 } NextArg⇐{ name‿gather 𝕊 type: a ← (name registers.Declare ⋈⟜@)⚇0 types.Unpack type atypes∾↩ ⟨ ⟨"call",Call _v1⟩, ⟨"emit",Emit _v1⟩, ⟨"return",Return⟩ ⟨"makelabel",Label⟩, ⟨"goto",(Goto 0⊸ReadLabel) _p1⟩ ⟨"setlabel",(SetLabel 1⊸ReadLabel) _p1 ⋈∘Label⍟(0=≠)⟩ ⟩ ∾ { New‿Union‿Has‿List ← architecture ⋄ S←SetArch ⋄ G←GetArch ⋄ ⟨ ⟨"setarch",S New⟩ ⟨"addarch",S G Union New⟩ ⟨"hasarch",G⊸Has⟩ ⟨"listarch",symbols.New¨List∘G⟩ ⟩} } blocks ← {kname⇐"block" New ⇐ {𝕊 ind‿ptrs‿body‿ls‿e: kind⇐kname shows⇐"{block}" ⋄ Matches⇐≡ Exec⇐{ "Wrong number of pointer arguments in block exec" ! ptrs≡○≠1⊑𝕩 r ← body.Eval be ← ⟨≠ind,ls,𝕩,ptrs⟩ env.Block e be.Stores @ r } } Exec ⇐ {𝕊 ind‿vars‿block: "Executing non-block" ! "block"≡Kind block block.Exec ind‿vars } } Load ← { 𝕊 ptr‿i: functions.Emit ⟨types.Deref TypeOf ptr, symbols.New "^load", ptr, i⟩ } Store← {v 𝕊 ptr‿i: functions.Emit ⟨types.Deref TypeOf ptr, symbols.New "^store", ptr, i, v⟩ } builtins ← { Kinds ← { E ← "Unhandled type" ! 0˙ (e{k‿o←𝕨⋄∧○(k≡⊢)◶⟨𝕏,O˙⟩}´𝕩){o←𝕨𝔽○Kind𝕩⋄𝕨O𝕩} } Ty2 ← {𝕏⚇0 _p2}∘Kinds ⊣∾⟜(<·"symbol"⌾⊑⊢´)∘⊢⍟(⊑∊⟜=‿≠)"number"‿"type"⋈¨{𝕏numbers._cmp}⊸⋈ TypeSuff ← IsTyped◶0‿{𝕩.fmtType}◶""‿{":"∾Fmt TypeOf𝕩} UnEsc ← ⊢-128×(' '+128)⊸= # Non-breaking space to space Fmt ← 2↓·∾·", "⊸∾¨(UnEsc∘Show∾TypeSuff)⎊("("∾")"∾˜Kind⎊"unknown")¨ Merge ← { 0<⌈´=¨𝕩 ? ∾𝕩 ; m←"merge: parameters must include at least one tuple or all be symbols" symbols.New ∾ m⊸symbols.From¨𝕩 } Slice ← { "slice: one or two slicing values expected"!(2⊸≤∧≤⟜3)≠𝕩 s←¬=l←⊑𝕩 l "slice: first parameter must be a tuple or symbol"⊸symbols.From⍟s↩ i←l≠⊸(0⌈⊣⌊+⍟(0⊸>)¨)numbers.From¨1↓𝕩 ⋄ symbols.New⍟s (⊑i)↓(1↓i)↑´˜l } names‿values ⇐ <˘∾≍⟨ Show¨⊸≍ types.primTypes ⍉> ⟨ ⟨"__set",functions.Mut _p2⟩ ⟨"show",(1≠≠)◶⊑‿{Shows⇐!∘"Multiple show used improperly"}⊣•Out∘Fmt⟩ ⟨"exec",blocks.Exec _e3⟩ ⟨"match",Match _p2⟩ ⟨"undefined",(constants.Undefined⊣"undefined: expected type"!"type"≡Kind)_p1⟩ ⟨"hastype",IsTyped∘⊑ _and_ ({𝕩.type}⊸Match´)_e2⟩ ⟨"type",TypeOf _p1⟩, ⟨"kind",symbols.New Kind _p1⟩ ⟨"typekind",symbols.New types.TypeKind _p1⟩ ⟨"load",Load _e2⟩, ⟨"store",¯1⊸(⊑Store↓)_e3⟩ ⟨"tup",⊢⟩, ⟨"tupsel",numbers.From⊸⊑⚇0‿∞ _p2⟩, ⟨"tuplen",≠_p1⟩ ⟨"merge",Merge⟩, ⟨"slice",Slice⟩ ⟨"symchars",(symbols.New∘⋈¨"symchars: expected symbol"⊸symbols.From)_p1⟩ ⟨"bind",⊑{𝕎𝕩⊸∾}1⊸↓_v1⟩, ⟨"each",⊑{𝕎¨<˘⍉>𝕩}1⊸↓_v1⟩ ⟨"apply",{"apply: second parameter must be a tuple"!1==𝕩⋄𝕎𝕩}_p2⟩ ⟨"export",{𝕨 symbols.From⊸program.Export⚇0 𝕩}_p2⟩ ⟨"require",{program.Require∘symbols.From⚇0 𝕩}⟩ ⟨"witharch",architecture.With⟩ ⟩ functions.builtins numbers.builtins types.builtins >⟨ "__eq"‿"__ne"‿"__lt"‿"__gt"‿"__le"‿"__ge" =‿≠‿<‿>‿≤‿≥ Ty2¨ ⟨Match,¬Match⟩ ∾ ·⥊≍˘⟜({𝕏˜}¨) ⟨types.SSubtype,types.Subtype⟩ ⟩ ⟩ values {name⇐𝕩}⊸{𝕏⊘𝕨}⍟(3=•Type∘⊢)¨˜↩ names } var ← { Get⇐{𝕩.Get 𝕨} Fixed⇐{ kind⇐"var" ⋄ Get⇐𝕩˙ } New⇐{𝕊: NG←"generator"≢Kind ⋄ kind⇐"var" Get⇐{! program._trace_ 𝕩 "Variable definition not yet reached"} Set⇐{ {𝕊:Set↩!∘"Can't extend a non-generator"}⍟NG 𝕩 Get ↩ 𝕩˙ 𝕩 } } } scopes ← { noLambda ← var.Fixed {!∘"Unhandled case"} null←{Get⇐{Err⟨"Undefined name: "∾𝕩,𝕨⟩} ⋄ GetLam⇐noLambda˙} New⇐{ p←@¨n←𝕨⊣⟨⟩ ⋄ Names⇐{𝕤⋄n} parent ⇐ 𝕩 # For nonlocal Sel ←{𝕩⊑env.Vars} Make←{c←≠n⋄p‿n∾⟜<¨↩𝕩⋄c} Dup ←{Err⟨"Duplicate definition:",⊑𝕩,"Previously defined here:",𝕨⊑p⟩} Par ←{𝕏∘env.Parent} _find ← { (n⊸⊐⌾<𝕩) =⟜(≠n)◶𝕗 𝕨‿𝕩 } Get ⇐ ⟨Sel⊣, Par 𝕩.Get´∘⊢⟩ _find Add ⇐ Sel Dup‿Make _find Lam ← Par⍟(noLambda⊸≢) 𝕩.GetLam´∘⊢ AddLam ⇐ ⟨⋈˜Sel∘⊣, Lam⋈Sel∘Make⟩ _find GetLam ⇐ ⟨Sel⊣, Lam⟩ _find } Init⇐New null˙ queue ← ⟨⟩ _defer ⇐ { queue∾↩<𝔽‿𝕩 } _run ⇐ { 𝔽 _defer 𝕩 _while_ ← {𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩} {𝕊:d←⊑queue⋄queue↓˜↩1⋄{𝕎𝕩}´d}_while_{𝕊:0<≠queue} @ } } env ← { Vars ⇐{𝕩.vars} Parent⇐{𝕩.parent} Make ←{ vars⇐𝕨 ⋄ parent⇐𝕩 } Alias⇐Make New ⇐{ (var.New¨ 𝕨) Make 𝕩 } Fixed⇐{ (var.Fixed¨ 𝕨) Make 𝕩 } Block⇐{⟨ni,Load‿Store,ind‿ptrs,names⟩ 𝕊 par: pv ← names functions.Declare⚇∞‿0⟜(Load∘⋈⟜ind)¨ ptrs vars‿parent ⇐ (var.Fixed¨(ni⥊⟨n,i,e⟩ # Adjust start and end i‿n‿e (iparamsPlus tname ← (¬∘∊⟜(⟨@⟩∾notTypeVar)⊸/ PhraseTryName¨)¨ ptype uTyp‿iTyp←(⍷∘∾ ⋈ ⊐∘∾⊔·/≠¨)tname _pc ← {n←𝕨⋄f←𝕗 ⋄ {pos Run ⟨Word f,⟨Word n,𝕩⟩⟩}¨𝕩} conds∾˜↩∾(params "hastype"_pc¨ tname≠⊸↓¨ptype)∾(params "match"_pc¨ pmatch) uPar‿iPar←(⍷⋈⊐)params ns ← pos⊸NewId¨ uPar∾uTyp Visit←{⟨𝕏¨ns,𝕏¨conds⟩} ⟨node,Dump,Disp,NonLocal,Oper,Scope⟩⇐Defaults "params"‿visit VisitLambda ⇐ {⟨(iPar⊏uPar)∾⟜(∾""<⊸∾":"⊸∾¨)¨tname,𝕏¨conds⟩} ScopeLambda ⇐ {(uPar∾uTyp) scopes.New 𝕩} AllEq ← ∧´⊏Match¨1⊸↓ proc ← {⊢} {e‿F‿N𝕊𝕩:e‿F𝕊⊑⟨𝕏N⟩; e‿1𝕊𝕩:𝕏; e‿F𝕊𝕩:f◶⟨