Last active
July 11, 2021 19:53
-
-
Save ovechkin-dm/6bed684db43d64a948440c96c137b08e to your computer and use it in GitHub Desktop.
Gofuck
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"errors" | |
"fmt" | |
"io" | |
"strings" | |
) | |
type State struct { | |
mem []byte | |
pos int | |
r io.Reader | |
} | |
type Op func(*State) error | |
func Right(state *State) error { | |
state.pos += 1 | |
if state.pos >= len(state.mem) { | |
return errors.New("out of bounds") | |
} | |
return nil | |
} | |
func Left(state *State) error { | |
state.pos -= 1 | |
if state.pos < 0 { | |
return errors.New("out of bounds") | |
} | |
return nil | |
} | |
func Print(state *State) error { | |
fmt.Print(string(state.mem[state.pos])) | |
return nil | |
} | |
func Read(state *State) error { | |
b := make([]byte, 1) | |
_, err := state.r.Read(b) | |
if err == io.EOF { | |
return nil | |
} | |
state.mem[state.pos] = b[0] | |
return err | |
} | |
func Plus(state *State) error { | |
state.mem[state.pos]++ | |
return nil | |
} | |
func Minus(state *State) error { | |
state.mem[state.pos]-- | |
return nil | |
} | |
type MyBufferedReader struct { | |
buf []byte | |
underlying io.Reader | |
pos int | |
} | |
func (r *MyBufferedReader) ReadToken() (byte, error) { | |
if r.pos < len(r.buf) { | |
result := r.buf[r.pos] | |
r.pos++ | |
return result, nil | |
} | |
token := make([]byte, 1) | |
_, err := r.underlying.Read(token) | |
if err != nil { | |
return 0, err | |
} | |
r.pos++ | |
r.buf = append(r.buf, token[0]) | |
return token[0], nil | |
} | |
type MyStack struct { | |
data []*StackContext | |
} | |
type StackContext struct { | |
pos int | |
condition bool | |
root bool | |
} | |
func (s *MyStack) pop() *StackContext { | |
elem := s.data[len(s.data)-1] | |
s.data = s.data[:len(s.data)-1] | |
return elem | |
} | |
func (s *MyStack) push(ctx *StackContext) { | |
s.data = append(s.data, ctx) | |
} | |
func (s *MyStack) get() (*StackContext, error) { | |
if s.len() == 0 { | |
return nil, errors.New("stack is empty") | |
} | |
return s.data[len(s.data)-1], nil | |
} | |
func (s *MyStack) len() int { | |
return len(s.data) | |
} | |
func Exec(reader *MyBufferedReader, state *State, ops map[string]Op) error { | |
stack := MyStack{ | |
data: make([]*StackContext, 0), | |
} | |
root := &StackContext{ | |
pos: 0, | |
condition: true, | |
root: true, | |
} | |
stack.push(root) | |
for { | |
token, err := reader.ReadToken() | |
if err == io.EOF { | |
return nil | |
} | |
if err != nil { | |
return err | |
} | |
tok := string(token) | |
err = validate(tok, ops) | |
if err != nil { | |
return err | |
} | |
c, err := stack.get() | |
if err != nil { | |
return err | |
} | |
if tok == "]" { | |
if c.root { | |
return errors.New("unexpected ]") | |
} | |
if state.mem[state.pos] != 0 { | |
reader.pos = c.pos - 1 | |
} | |
_ = stack.pop() | |
} else if tok == "[" { | |
ctx := StackContext{ | |
pos: reader.pos, | |
condition: state.mem[state.pos] != 0, | |
root: false, | |
} | |
stack.push(&ctx) | |
} else { | |
if !c.condition { | |
continue | |
} | |
op, ok := ops[tok] | |
if !ok { | |
continue | |
} | |
err = op(state) | |
if err != nil { | |
return err | |
} | |
} | |
} | |
} | |
func validate(tok string, ops map[string]Op) error { | |
//TODO: actually validate! | |
return nil | |
} | |
func Run(reader io.Reader, input io.Reader) error { | |
r := MyBufferedReader{ | |
buf: make([]byte, 0), | |
underlying: reader, | |
pos: 0, | |
} | |
state := State{ | |
mem: make([]byte, 30000), | |
pos: 0, | |
r: input, | |
} | |
ops := make(map[string]Op) | |
ops["+"] = Plus | |
ops["-"] = Minus | |
ops[">"] = Right | |
ops["<"] = Left | |
ops["."] = Print | |
ops[","] = Read | |
err := Exec(&r, &state, ops) | |
return err | |
} | |
func main() { | |
//prog := "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++++++.+++++++..+++.-------------------------------------------------------------------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++++++.+++.------.--------.-------------------------------------------------------------------.-----------------------." | |
//prog := "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." | |
prog := ">>>+>>>>>+>>+>>+[<<],[\n -[-[-[-[-[-[-[-[<+>-[>+<-[>-<-[-[-[<++[<++++++>-]<\n [>>[-<]<[>]<-]>>[<+>-[<->[-]]]]]]]]]]]]]]]]\n <[-<<[-]+>]<<[>>>>>>+<<<<<<-]>[>]>>>>>>>+>[\n <+[\n >+++++++++<-[>-<-]++>[<+++++++>-[<->-]+[+>>>>>>]]\n <[>+<-]>[>>>>>++>[-]]+<\n ]>[-<<<<<<]>>>>\n ],\n ]+<++>>>[[+++++>>>>>>]<+>+[[<++++++++>-]<.<<<<<]>>>>>>>>]" | |
input := "test1 test2\ntest3 tttt" | |
reader := bufio.NewReader(strings.NewReader(prog)) | |
err := Run(reader, strings.NewReader(input)) | |
if err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment