Skip to content
This repository has been archived by the owner on Mar 15, 2019. It is now read-only.

Commit

Permalink
support array literal, closes #36
Browse files Browse the repository at this point in the history
  • Loading branch information
mna committed Nov 12, 2013
1 parent dabf335 commit 4679f88
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 57 deletions.
2 changes: 1 addition & 1 deletion bytecode/build.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package bytecode
const (
AGORA_BUILD = "8405c1e"
AGORA_BUILD = "dabf335"
)
51 changes: 27 additions & 24 deletions bytecode/instr.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,43 @@ const (
FLG_Jb // Jump back over n instructions
FLG_Sn // Dump n frames
FLG_Fn // Set n fields
FLG_Fn2 // Set n field pairs
FLG_INVL Flag = 0xFF // Invalid flag
)

var (
// The lookup table of Flag values to literal flag names
FlagNames = [...]string{
FLG__: "_",
FLG_K: "K",
FLG_V: "V",
FLG_F: "F",
FLG_A: "A",
FLG_N: "N",
FLG_T: "T",
FLG_An: "An",
FLG_Jf: "Jf",
FLG_Jb: "Jb",
FLG_Sn: "Sn",
FLG_Fn: "Fn",
FLG__: "_",
FLG_K: "K",
FLG_V: "V",
FLG_F: "F",
FLG_A: "A",
FLG_N: "N",
FLG_T: "T",
FLG_An: "An",
FLG_Jf: "Jf",
FLG_Jb: "Jb",
FLG_Sn: "Sn",
FLG_Fn: "Fn",
FLG_Fn2: "Fn2",
}

// The lookup table of literal flag names to Flag values
FlagLookup = map[string]Flag{
"_": FLG__,
"K": FLG_K,
"V": FLG_V,
"F": FLG_F,
"A": FLG_A,
"N": FLG_N,
"T": FLG_T,
"An": FLG_An,
"Jf": FLG_Jf,
"Jb": FLG_Jb,
"Sn": FLG_Sn,
"Fn": FLG_Fn,
"_": FLG__,
"K": FLG_K,
"V": FLG_V,
"F": FLG_F,
"A": FLG_A,
"N": FLG_N,
"T": FLG_T,
"An": FLG_An,
"Jf": FLG_Jf,
"Jb": FLG_Jb,
"Sn": FLG_Sn,
"Fn": FLG_Fn,
"Fn2": FLG_Fn2,
}
)

Expand Down
19 changes: 16 additions & 3 deletions compiler/emitter/emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,20 @@ func (e *Emitter) emitSymbol(f *bytecode.File, fn *bytecode.Fn, sym *parser.Symb
case "args":
e.assert(asg == atFalse, errors.New("invalid assignment to the `args` keyword"))
e.addInstr(fn, bytecode.OP_PUSH, bytecode.FLG_A, 0)
case ".", "[":
case "[":
if sym.Ar == parser.ArLiteral {
// Array literal
ln := 0
if !e.isEmpty(sym.First) {
syms := sym.First.([]*parser.Symbol)
ln = len(syms)
e.emitBlock(f, fn, syms)
}
e.addInstr(fn, bytecode.OP_NEW, bytecode.FLG_Fn, uint64(ln))
break
}
fallthrough
case ".":
e.assert(sym.Ar == parser.ArBinary, errors.New("expected `"+sym.Id+"` to have binary arity"))
e.emitSymbol(f, fn, sym.Second.(*parser.Symbol), atFalse)
e.emitSymbol(f, fn, sym.First.(*parser.Symbol), atFalse)
Expand Down Expand Up @@ -283,15 +296,15 @@ func (e *Emitter) emitSymbol(f *bytecode.File, fn *bytecode.Fn, sym *parser.Symb
// Call
e.addInstr(fn, op, bytecode.FLG_An, uint64(len(parms)))
case "{":
e.assert(sym.Ar == parser.ArUnary, errors.New("expected `{` to have unary arity"))
e.assert(sym.Ar == parser.ArLiteral, errors.New("expected `{` to have literal arity"))
ln := 0
if !e.isEmpty(sym.First) {
e.emitAny(f, fn, sym, sym.First)
if ar, ok := sym.First.([]*parser.Symbol); ok {
ln = len(ar)
}
}
e.addInstr(fn, bytecode.OP_NEW, bytecode.FLG__, uint64(ln))
e.addInstr(fn, bytecode.OP_NEW, bytecode.FLG_Fn2, uint64(ln))
case "?":
// Similar to if, but yields a value
e.assert(sym.Ar == parser.ArTernary, errors.New("expected `?` to have ternary arity"))
Expand Down
59 changes: 33 additions & 26 deletions compiler/parser/grammar.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ func (p *Parser) defineGrammar() {
p.advance("]")
return sym
})
p.prefix("[", func(sym *Symbol) *Symbol {
var ar []*Symbol
for p.tkn.Id != "]" && p.tkn.Id != ";" {
ar = append(ar, p.expression(0))
if p.tkn.Id != "," {
break
}
p.advance(",")
}
p.advance("]")
sym.First = ar
sym.Ar = ArLiteral
return sym
})

// The logical operators
p.infixr("&&", 30, nil)
Expand Down Expand Up @@ -248,14 +262,12 @@ func (p *Parser) defineGrammar() {
// The function/method call parser
p.infix("(", 80, func(sym, left *Symbol) *Symbol {
var a []*Symbol
if p.tkn.Id != ")" {
for {
a = append(a, p.expression(0))
if p.tkn.Id != "," {
break
}
p.advance(",")
for p.tkn.Id != ")" && p.tkn.Id != ";" {
a = append(a, p.expression(0))
if p.tkn.Id != "," {
break
}
p.advance(",")
}
p.advance(")")
if left.Id == "." || left.Id == "[" {
Expand Down Expand Up @@ -293,29 +305,24 @@ func (p *Parser) defineGrammar() {
// The object literal notation
p.prefix("{", func(sym *Symbol) *Symbol {
var a []*Symbol
if p.tkn.Id != "}" {
for {
n := p.tkn
if n.Ar != ArName && n.Ar != ArLiteral {
p.error(n, "bad key")
}
p.advance(_SYM_ANY)
p.advance(":")
v := p.expression(0)
v.Key = n.Val
a = append(a, v)
if p.tkn.Id != "," {
break
}
p.advance(",")
if p.tkn.Id == "}" {
break
}
for p.tkn.Id != "}" && p.tkn.Id != ";" {
n := p.tkn
if n.Ar != ArName && n.Ar != ArLiteral {
p.error(n, "bad key")
}
p.advance(_SYM_ANY)
p.advance(":")
v := p.expression(0)
v.Key = n.Val
a = append(a, v)
if p.tkn.Id != "," {
break
}
p.advance(",")
}
p.advance("}")
sym.First = a
sym.Ar = ArUnary
sym.Ar = ArLiteral
return sym
})

Expand Down
13 changes: 10 additions & 3 deletions runtime/funcvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,16 @@ func (f *agoraFuncVM) run(args ...Val) Val {

case bytecode.OP_NEW:
ob := NewObject()
for j := ix; j > 0; j-- {
key, val := f.pop(), f.pop()
ob.Set(key, val)
if flg == bytecode.FLG_Fn2 {
for j := ix; j > 0; j-- {
key, val := f.pop(), f.pop()
ob.Set(key, val)
}
} else if flg == bytecode.FLG_Fn {
for j := ix; j > 0; j-- {
val := f.pop()
ob.Set(Number(j-1), val)
}
}
f.push(ob)

Expand Down
6 changes: 6 additions & 0 deletions testdata/src/82-array.agora
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*---
output: {1:2,0:1}\n
---*/
fmt := import("fmt")
a := [1, 2]
fmt.Println(a)

0 comments on commit 4679f88

Please sign in to comment.