Implement for.

This commit is contained in:
Qi Xiao 2016-02-14 19:42:08 +01:00
parent 26006a03f4
commit ec9a628ba0
4 changed files with 45 additions and 31 deletions

View File

@ -77,14 +77,14 @@ func assignmentBegins(ns []*parse.Assignment) []int {
return begins return begins
} }
func (cp *compiler) indexingVars(ns []*parse.Indexing, msg string) []VariableOp { func (cp *compiler) singleVariables(ns []*parse.Indexing, msg string) []VariableOp {
ops := make([]VariableOp, len(ns)) ops := make([]VariableOp, len(ns))
for i, n := range ns { for i, n := range ns {
ops[i] = cp.indexingVar(n, msg) ops[i] = cp.singleVariable(n, msg)
} }
return ops return ops
} }
func indexingVarBegins(ns []*parse.Indexing) []int { func singleVariableBegins(ns []*parse.Indexing) []int {
begins := make([]int, len(ns)) begins := make([]int, len(ns))
for i, n := range ns { for i, n := range ns {
begins[i] = n.Begin() begins[i] = n.Begin()

View File

@ -277,8 +277,17 @@ func (cp *compiler) control(n *parse.Control) Op {
} }
} }
case parse.ForControl: case parse.ForControl:
cp.errorf(n.Begin(), "not yet implemented") iteratorOp := cp.singleVariable(n.Iterator, "must be a single variable")
panic("unreachable") valuesOp := cp.array(n.Array)
bodyOp := cp.chunk(n.Body)
return func(ec *EvalCtx) {
iterator := iteratorOp(ec)
values := valuesOp(ec)
for _, v := range values {
doSet(ec, []Variable{iterator}, []Value{v})
bodyOp(ec)
}
}
case parse.BeginControl: case parse.BeginControl:
return cp.chunk(n.Body) return cp.chunk(n.Body)
default: default:
@ -298,21 +307,7 @@ func (cp *compiler) literal(n *parse.Primary, msg string) string {
} }
func (cp *compiler) assignment(n *parse.Assignment) Op { func (cp *compiler) assignment(n *parse.Assignment) Op {
var variableOps []VariableOp variableOps := cp.multiVariable(n.Dst)
if n.Dst.Head.Type == parse.Braced {
compounds := n.Dst.Head.Braced
indexings := make([]*parse.Indexing, len(compounds))
for i, cn := range compounds {
if len(cn.Indexings) != 1 {
cp.errorf(cn.Begin(), "must be a variable spec")
}
indexings[i] = cn.Indexings[0]
}
variableOps = cp.indexingVars(indexings, "must be a variable spc")
} else {
variableOps = []VariableOp{cp.indexingVar(n.Dst, "must be a variable spec or a braced list of those")}
}
valuesOp := cp.compound(n.Src) valuesOp := cp.compound(n.Src)
return func(ec *EvalCtx) { return func(ec *EvalCtx) {
@ -324,8 +319,27 @@ func (cp *compiler) assignment(n *parse.Assignment) Op {
} }
} }
func (cp *compiler) indexingVar(n *parse.Indexing, msg string) VariableOp { func (cp *compiler) multiVariable(n *parse.Indexing) []VariableOp {
// XXX will we be using indexingVar for purposes other than setting? var variableOps []VariableOp
if n.Head.Type == parse.Braced {
// XXX ignore n.Indicies.
compounds := n.Head.Braced
indexings := make([]*parse.Indexing, len(compounds))
for i, cn := range compounds {
if len(cn.Indexings) != 1 {
cp.errorf(cn.Begin(), "must be a variable spec")
}
indexings[i] = cn.Indexings[0]
}
variableOps = cp.singleVariables(indexings, "must be a variable spc")
} else {
variableOps = []VariableOp{cp.singleVariable(n, "must be a variable spec or a braced list of those")}
}
return variableOps
}
func (cp *compiler) singleVariable(n *parse.Indexing, msg string) VariableOp {
// XXX will we be using this for purposes other than setting?
varname := cp.literal(n.Head, msg) varname := cp.literal(n.Head, msg)
p := n.Begin() p := n.Begin()

View File

@ -92,7 +92,7 @@ func (n *Control) setCondition(ch *Chunk) {
addChild(n, ch) addChild(n, ch)
} }
func (n *Control) setIterator(ch *Primary) { func (n *Control) setIterator(ch *Indexing) {
n.Iterator = ch n.Iterator = ch
addChild(n, ch) addChild(n, ch)
} }

View File

@ -287,7 +287,7 @@ type Control struct {
node node
Kind ControlKind Kind ControlKind
Condition *Chunk // Valid for WhileControl. Condition *Chunk // Valid for WhileControl.
Iterator *Primary // Valid for ForControl. Iterator *Indexing // Valid for ForControl.
Array *Array // Valid for ForControl. Array *Array // Valid for ForControl.
Body *Chunk // Valid for all except IfControl. Body *Chunk // Valid for all except IfControl.
Conditions []*Chunk // Valid for IfControl. Conditions []*Chunk // Valid for IfControl.
@ -374,7 +374,7 @@ func (ctrl *Control) parse(ps *parser, leader string) {
case "for": case "for":
ctrl.Kind = ForControl ctrl.Kind = ForControl
parseSpaces(ctrl, ps) parseSpaces(ctrl, ps)
ctrl.setIterator(parsePrimary(ps)) ctrl.setIterator(parseIndexing(ps))
parseSpaces(ctrl, ps) parseSpaces(ctrl, ps)
if ps.findPossibleLeader() == "in" { if ps.findPossibleLeader() == "in" {
ps.advance(len("in")) ps.advance(len("in"))