first.go (5163B)
1 package main 2 3 import ( 4 "fmt" 5 "bufio" 6 "os" 7 "io" 8 "strconv" 9 "strings" 10 ) 11 12 const ( 13 rsp int = 1 14 dep int = 0 15 16 rstacksize = 512 17 rstackstart = 32 18 ) 19 20 var laswor string 21 22 type Mem struct { 23 data []int 24 } 25 26 func NewMem() *Mem { 27 var mem = new(Mem) 28 mem.data = make([]int, 0) 29 return mem 30 } 31 32 func (m *Mem) Fetch(addr int) (int, error) { 33 if (addr >= len(m.data)) || (addr < 0) { 34 return 0, fmt.Errorf("memfetch: addr %d out of bonds", addr) 35 } 36 return m.data[addr], nil 37 } 38 39 func (m *Mem) Store(addr, val int) { 40 if addr >= len(m.data) { 41 buf := make([]int, addr - len(m.data) + 1) 42 m.data = append(m.data, buf...) 43 } 44 m.data[addr] = val 45 } 46 47 type Stack struct { 48 data []int 49 } 50 51 func NewStack() *Stack { 52 stack := new(Stack) 53 stack.data = make([]int, 1) 54 return stack 55 } 56 57 func (s *Stack) Push(val int) { 58 s.data = append(s.data, val) 59 } 60 61 func (s *Stack) Pop() (int, error) { 62 if s.data == nil { 63 return 0, fmt.Errorf("stack is empty") 64 } 65 x := s.data[len(s.data) - 1] 66 s.data = s.data[:len(s.data) - 1] 67 return x, nil 68 } 69 70 func (s *Stack) TOS() *int { 71 return &s.data[len(s.data) - 1] 72 } 73 74 type First struct { 75 stack *Stack 76 mem *Mem 77 strings []string 78 pc, lwp int 79 run bool 80 in *bufio.Reader 81 } 82 83 func NewFirst() (*First, error) { 84 const builtins string = ": immediate _read @ ! - * / <0 exit echo key _pick" 85 first := new(First) 86 *first = First{ 87 NewStack(), 88 NewMem(), 89 make([]string, 0), 90 0, 0, 91 true, 92 nil, 93 } 94 first.mem.Store(dep, rstackstart + rstacksize) 95 first.mem.Store(rsp, rstackstart) 96 first.in = bufio.NewReader(strings.NewReader(builtins)) 97 98 first.define(3) 99 first.define(4) 100 first.define(1) 101 loopword := first.mem.data[dep] 102 first.Compile(5, 2) 103 first.pc = first.mem.data[dep] 104 first.Compile(loopword, first.pc - 1) 105 for i := 6; i < 16; i++ { 106 first.define(1) 107 first.Compile(i) 108 } 109 return first, nil 110 } 111 112 func (F *First) findWord(s string) int { 113 var err error 114 for wp := F.lwp; wp != 0; wp, err = F.mem.Fetch(wp) { 115 if err != nil { 116 return 0 117 } 118 id, err := F.mem.Fetch(wp + 1) 119 if err != nil { 120 return 0 121 } 122 if F.strings[id] == s { 123 return wp 124 } 125 } 126 return 0 127 } 128 129 func (F *First) rpush(val int) (error) { 130 if F.mem.data[rsp] >= rstacksize + rstackstart { 131 return fmt.Errorf("rstack is full") 132 } 133 F.mem.data[rsp]++ 134 F.mem.Store(F.mem.data[rsp], val) 135 return nil 136 } 137 138 func (F *First) rpop() (int, error) { 139 if F.mem.data[rsp] <= rstackstart { 140 return 0, fmt.Errorf("rstack is empty") 141 } 142 x, err := F.mem.Fetch(F.mem.data[rsp]) 143 F.mem.data[rsp]-- 144 return x, err 145 } 146 147 func (F *First) Compile(vals ...int) { 148 for _, val := range vals { 149 F.mem.Store(F.mem.data[dep], val) 150 F.mem.data[dep]++ 151 } 152 } 153 154 func (F *First) define(code int) error { 155 var s string 156 F.Compile(F.lwp) 157 F.lwp = F.mem.data[dep] - 1 158 F.Compile(len(F.strings), code) 159 if _, err := fmt.Fscan(F.in, &s); err != nil { 160 return err 161 } 162 F.strings = append(F.strings, s) 163 return nil 164 } 165 166 func (F *First) _read() error { 167 var ( 168 s string 169 num, wp int 170 err error 171 ) 172 if _, err = fmt.Fscan(F.in, &s); err != nil { 173 return err 174 } 175 wp = F.findWord(s) 176 if wp != 0 { 177 return F.Step(wp + 2) 178 } 179 if num, err = strconv.Atoi(s); err != nil { 180 return err 181 } 182 F.Compile(2, num) 183 return nil 184 } 185 186 func (F *First) Run(input *bufio.Reader) error { 187 F.in = input 188 var ( 189 addr int 190 err error 191 ) 192 for err == nil { 193 addr, err = F.mem.Fetch(F.pc) 194 F.pc++ 195 if err != nil { 196 break 197 } 198 err = F.Step(addr) 199 } 200 if err == io.EOF { 201 return nil 202 } 203 return err 204 } 205 206 func (F *First) Step(addr int) error { 207 var x, y int 208 inst, err := F.mem.Fetch(addr) 209 addr++ 210 switch inst { 211 case 0: // internal builtin "pushint" 212 x, err = F.mem.Fetch(F.pc) 213 F.pc++ 214 F.stack.Push(x) 215 case 1: // compile 216 F.Compile(addr) 217 case 2: // run 218 F.rpush(F.pc) 219 F.pc = addr 220 case 3: // builtin "define", ":" 221 err = F.define(1) 222 F.Compile(2) 223 case 4: // builtin "immediate" 224 F.mem.data[dep] -= 2 225 F.Compile(2) 226 case 5: // builtin "_read" 227 err = F._read() 228 case 6: // builtin "fetch", "@" 229 x, err = F.stack.Pop() 230 y, err = F.mem.Fetch(x) 231 F.stack.Push(y) 232 case 7: // builtin "store", "!" 233 x, err = F.stack.Pop() 234 y, err = F.stack.Pop() 235 F.mem.Store(x, y) 236 case 8: // builtin "minus", "-" 237 x, err = F.stack.Pop() 238 y, err = F.stack.Pop() 239 F.stack.Push(y - x) 240 case 9: // builtin "mulitply", "*" 241 x, err = F.stack.Pop() 242 y, err = F.stack.Pop() 243 F.stack.Push(y * x) 244 case 10: // builtin "divide", "/" 245 x, err = F.stack.Pop() 246 y, err = F.stack.Pop() 247 F.stack.Push(y / x) 248 case 11: // builtin "less than 0", "<0" 249 x, err = F.stack.Pop() 250 if (x < 0) { 251 F.stack.Push(1) 252 } else { 253 F.stack.Push(0) 254 } 255 case 12: // builtin "exit" 256 F.pc, err = F.rpop() 257 case 13: // builtin "echo" 258 x, err = F.stack.Pop() 259 if err == nil { 260 fmt.Printf("%c", x) 261 } 262 case 14: // builtin "key" 263 var r rune 264 r, _, err = F.in.ReadRune() 265 F.stack.Push(int(r)) 266 case 15: // builtin "_pick" 267 x, err = F.stack.Pop() 268 y = F.stack.data[len(F.stack.data) - x - 1] 269 F.stack.Push(y) 270 default: 271 err = fmt.Errorf("unexpected instruction %d", inst) 272 } 273 return err 274 } 275 276 func main() { 277 first, err := NewFirst() 278 if err != nil { 279 fmt.Println(err) 280 } else if err = first.Run(bufio.NewReader(os.Stdin)); 281 err != nil { 282 fmt.Println(err) 283 } 284 }