aboutsummaryrefslogtreecommitdiff
path: root/vm.bqn
blob: 34f4be605240ecdef18ecbea8c6bc181bcb0bcde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
MakeVar โ† {๐•ค
  vโ†@
  Get  โ‡ !โˆ˜"Runtime: Variable referenced before definition"
  SetU โ‡ !โˆ˜"โ†ฉ: Variable modified before definition"
  SetN โ‡ {
    Get โ†ฉ {๐•คโ‹„v}
    (SetU โ†ฉ {vโ†ฉ๐•ฉ}) ๐•ฉ
  }
  SetQ โ‡ 0โˆ˜SetN
  GetC โ‡ {
    r โ† Get๐•ฉ
    Getโ†ฉSetUโ†ฉSetNโ†ฉ!โˆ˜"Internal error: Variable used after clear"
    r
  }
}
MakeEnv โ† {
  vars โ‡ MakeVarยจ โ†•๐•จ
  parent โ‡ ๐•ฉ
  program โ‡ ๐•ฉ.program
}

VO โ† { dโ†๐•@, sโ†๐•@, sโŠ‘ยท{๐•ฉ.vars}{๐•ฉ.parent}โŸd }

nothing  โ† {โ‡}
skipMark โ† {โ‡}

Namespace โ† !
ReadNS โ† !

ref โ† {
  Matcher โ‡ {๐•Š const:
    SetQ โ‡ constห™ โ‰ข โŠข
  }
  Array โ‡ {๐•Š arr:
    Get  โ‡ {๐•ฉ.Get@}ยจ arrห™
    _set โ† {arr โ‰กโ—‹โ‰ขโ—ถโŸจ!, ๐•—ยจโŸฉ โŠข}
    SetN โ‡ {๐•จ.SetN๐•ฉ}_set
    SetU โ‡ {๐•จ.SetU๐•ฉ}_set
    SetQ โ‡ arr โ‰กโ—‹โ‰ขโ—ถโŸจ1, โˆจยด{๐•จ.SetQ๐•ฉ}ยจโŸฉ โŠข
  }
}

Get โ† {๐•ฉ.Get @}โš‡0

MakeStack โ† {
  s โ† ๐•ฉ                          # Stack (a list)
  cont โ‡ 1                       # Whether to continue execution
  rslt โ‡ skipMark                # Result: skipMark to abort current body
  Push โ‡ {sโˆพโ†ฉ<๐•ฉ}                 # Push a value
  Pop  โ‡ {tโ†-๐•ฉ โ‹„ (sโ†“หœโ†ฉt) โŠข โŒฝtโ†‘s} # Pop ๐•ฉ values; return as list
  Peek โ‡ {๐•คโ‹„ยฏ1โŠ‘s}                # Return but don't pop top value
  Ret  โ‡ {rsltโ†ฉ๐•ฉ โ‹„ contโ†ฉ0 โ‹„ "Internal compiler error: Wrong stack size"!0=โ‰ s}
  Skip โ‡ {๐•คโ‹„       contโ†ฉ0}
}

ops โ† ((!โˆ˜"Unknown opcode")ห™โŠฃยดโŠข)ยจ โŠ”ห โ‰> โŸจ
  # Constants and drop
   0โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push         iโŠ‘e.program.consts } }
   1โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push e {๐•Ž๐•ฉ}หœ iโŠ‘e.program.blocks } }
   6โ€ฟ(       {s๐•Še: s.Pop 1 }ห™)
  # Returns
   7โ€ฟ(       {s๐•Še: 0 s.Ret โŠ‘s.Pop 1 }ห™)
   8โ€ฟ(       {s๐•Še: 1 s.Ret Namespace e }ห™)
  # Arrays
  11โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push           โŒฝs.Pop i } }
  12โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push ref.Array โŒฝs.Pop i } }
  # Application
  16โ€ฟ(       {s๐•Še: s.Push {   fโ€ฟx:   F x }   s.Pop 2 }ห™)
  17โ€ฟ(       {s๐•Še: s.Push { wโ€ฟfโ€ฟx: w F x }   s.Pop 3 }ห™)
  20โ€ฟ(       {s๐•Še: s.Push {   gโ€ฟh:   G H }   s.Pop 2 }ห™)
  21โ€ฟ(       {s๐•Še: s.Push { fโ€ฟgโ€ฟh: F G H }   s.Pop 3 }ห™)
  26โ€ฟ(       {s๐•Še: s.Push { fโ€ฟm  : F _m    } s.Pop 2 }ห™)
  27โ€ฟ(       {s๐•Še: s.Push { fโ€ฟmโ€ฟg: F _m_ g } s.Pop 3 }ห™)
  # Application with Nothing
  18โ€ฟ(       {s๐•Še: s.Push {   fโ€ฟx:                    FโŸ(nothingโŠธโ‰ข) x } s.Pop 2 }ห™) # Like 16
  19โ€ฟ(       {s๐•Še: s.Push { wโ€ฟfโ€ฟx: (nothingโ‰ขwห™)โ—ถโŸจF,wโŠธFโŸฉโŸ(nothingโŠธโ‰ข) x } s.Pop 3 }ห™) # Like 17
  23โ€ฟ(       {s๐•Še: s.Push { fโ€ฟgโ€ฟh: {fโ‰กnothing?G H;F G H}              } s.Pop 3 }ห™) # Like 21
  22โ€ฟ(       {s๐•Še: "Left argument required" ! nothingโ‰ขs.Peek@ }ห™)
  # Variables
  32โ€ฟ{vโ†VO๐•ฉโ‹„ {s๐•Še: s.Push (V e).Get @ } }
  34โ€ฟ{vโ†VO๐•ฉโ‹„ {s๐•Še: s.Push (V e).GetC@ } }
  33โ€ฟ{vโ†VO๐•ฉโ‹„ {s๐•Še: s.Push  V e        } }
  # Headers
  42โ€ฟ(       {s๐•Še: {0:s.Skip@; 1:@; ๐•Š:!"Predicate value must be 0 or 1"} โŠ‘s.Pop 1 }ห™)
  43โ€ฟ(       {s๐•Še: s.Push ref.Matcher โŠ‘s.Pop 1 }ห™)
  # Assignment
  47โ€ฟ(       {s๐•Še: s.SkipโŸโŠข{rโ€ฟ  v: r.SetQ v           } s.Pop 2 }ห™)  # r:
  48โ€ฟ(       {s๐•Še: s.Push { rโ€ฟ  v: r.SetN v           } s.Pop 2 }ห™)  # r  โ†v
  49โ€ฟ(       {s๐•Še: s.Push { rโ€ฟ  v: r.SetU v           } s.Pop 2 }ห™)  # r  โ†ฉv
  50โ€ฟ(       {s๐•Še: s.Push { rโ€ฟfโ€ฟx: r.SetU (r.Get@)F x } s.Pop 3 }ห™)  # r Fโ†ฉx
  51โ€ฟ(       {s๐•Še: s.Push { rโ€ฟf  : r.SetU F r.Get@    } s.Pop 2 }ห™)  # r Fโ†ฉ
  # Namespaces
  64โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push eโ€ฟi ReadNS    โŠ‘s.Pop 1 } }
  66โ€ฟ{iโ†๐•@ โ‹„ {s๐•Še: s.Push eโ€ฟi ref.Alias โŠ‘s.Pop 1 } }
โŸฉ

RunBC โ† { bcโ€ฟposโ€ฟenv:
  Next โ† {๐•คโ‹„ (pos+โ†ฉ1) โŠข posโŠ‘bc }
  stack โ† MakeStack โŸจโŸฉ
  Step โ† {๐•Š:
    op โ† (Next@) โŠ‘ ops
    op โ†ฉ Op next
    stack Op env
    stack.cont
  }
  _while_ โ† {๐”ฝโŸ๐”พโˆ˜๐”ฝ_๐•ฃ_๐”พโˆ˜๐”ฝโŸ๐”พ๐•ฉ}
  Step _while_ โŠข 1
  stack.rslt
}

{ VM bcโ€ฟconstsโ€ฟblockInfoโ€ฟbodyInfoโ€ฟlocโ€ฟtoken:

  bodies โ† {startโ€ฟvarsโ€ฟnamesโ€ฟexport:
    {parent ๐•Š args:
      env โ† vars MakeEnv parent  # names/export?
      (โŠข {๐•ฉ.SetN ๐•จ}ยจ โ‰ โ†‘env.varsห™) args
      RunBC bcโ€ฟstartโ€ฟenv
    }
  }ยจ bodyInfo

  blocks โ† {typeโ€ฟimmโ€ฟbody:
    inner โ† type โŠ‘ โŸจ
      {๐•Šn: N โŸจโŸฉ}
      {๐•Šn: {N ๐•ฃโ€ฟ๐•—  }}
      {๐•Šn: {N ๐•ฃโ€ฟ๐•—โ€ฟ๐•˜}}
    โŸฉ
    outer โ† imm โŠ‘ โŸจ
      {
        mโ€ฟd: {๐•Šv: {M ๐•คโ€ฟ๐•ฉโ€ฟnothingโˆพv;D ๐•คโ€ฟ๐•ฉโ€ฟ๐•จโˆพv}} ;
        โŸจbโŸฉ: {๐•Šv: {B ๐•คโ€ฟ๐•ฉโ€ฟ(๐•จโŠฃnothing)โˆพv}}
      }
      โŠ‘
    โŸฉ

    nmc โ† "No matching case"
    Then โ† {first ๐•Š next: {skipMarkโ‰ขrโ†๐•จFirst๐•ฉ ? r ; ๐•จNext๐•ฉ}}
    run โ† {
      1=โ€ขType ๐•ฉ ?
      โŸจ(๐•ฉโŠ‘bodies) Then {!โˆ˜nmc}โŸฉ
    ;
      "Internal compiler error: Invalid body indices" ! 1==๐•ฉ
      ! (โ‰ ๐•ฉ) โ‰ก 2-imm
      e โ† {imm ? โŸจnmcโŸฉ ;
        (0=โ‰ ยจ๐•ฉ) nmcโŸโŠฃยจ "Left argument "โŠธโˆพยจโŸจ"not allowed","required"โŸฉ
      }๐•ฉ
      ๐•ฉ ThenยดโŸœ(โŠโŸœbodies)หœโŸœ{!โˆ˜๐•ฉ}ยจ e
    } body
    {๐•Š parent:
      Inner Outer {parentห™ ๐• โŠข}ยจ run
    }
  }ยจ blockInfo
  
  program โ† {
    constsโ‡consts
    blocksโ‡blocks
  }
  
  (โŠ‘blocks){๐”ฝ} {programโ‡program}
}