github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/compiler.go (about) 1 package compiler 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 9 "github.com/hirochachacha/plua/compiler/codegen" 10 "github.com/hirochachacha/plua/compiler/parser" 11 "github.com/hirochachacha/plua/compiler/scanner" 12 "github.com/hirochachacha/plua/compiler/undump" 13 "github.com/hirochachacha/plua/internal/version" 14 "github.com/hirochachacha/plua/object" 15 ) 16 17 type FormatType uint 18 19 const ( 20 Either FormatType = iota 21 Text 22 Binary 23 ) 24 25 func (typ FormatType) String() string { 26 switch typ { 27 case Either: 28 return "either" 29 case Text: 30 return "text" 31 case Binary: 32 return "binary" 33 default: 34 return "unexpected" 35 } 36 } 37 38 type Compiler struct { 39 s *scanner.ScanState 40 r *bufio.Reader 41 } 42 43 func NewCompiler() *Compiler { 44 return new(Compiler) 45 } 46 47 func (c *Compiler) Compile(r io.Reader, srcname string, typ FormatType) (*object.Proto, error) { 48 49 if c.r == nil { 50 c.r = bufio.NewReader(r) 51 } else { 52 c.r.Reset(r) 53 } 54 55 b, err := c.r.Peek(1) 56 57 switch { 58 case err == io.EOF, err == nil && b[0] != version.LUA_SIGNATURE[0]: 59 if typ != Either && typ != Text { 60 return nil, &Error{fmt.Errorf("compiler: attempt to load a %s chunk (mode is '%s')", "text", typ)} 61 } 62 63 if c.s == nil { 64 c.s = scanner.Scan(c.r, srcname, 0) 65 } else { 66 c.s.Reset(c.r, srcname, 0) 67 } 68 69 ast, err := parser.Parse(c.s, 0) 70 if err != nil { 71 return nil, err 72 } 73 74 return codegen.Generate(ast) 75 case err == nil && b[0] == version.LUA_SIGNATURE[0]: 76 if typ != Either && typ != Binary { 77 return nil, &Error{fmt.Errorf("compiler: attempt to load a %s chunk (mode is '%s')", "binary", typ)} 78 } 79 80 return undump.Undump(c.r, 0) 81 default: 82 return nil, err 83 } 84 } 85 86 func (c *Compiler) CompileFile(path string, typ FormatType) (*object.Proto, error) { 87 f, err := os.Open(path) 88 if err != nil { 89 return nil, err 90 } 91 defer f.Close() 92 93 return c.Compile(f, "@"+f.Name(), typ) 94 }