Skip to content

Commit 3965a79

Browse files
committed
compile: implement subscript and fix attribute
1 parent cd8c5fa commit 3965a79

File tree

5 files changed

+1627
-30
lines changed

5 files changed

+1627
-30
lines changed

compile/compile.go

+138-23
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
960960
panic("compile: can't set context in AugAssign")
961961
}
962962
// FIXME untidy modifying the ast temporarily!
963-
setctx.SetCtx(ast.Load)
963+
setctx.SetCtx(ast.AugLoad)
964964
c.Expr(node.Target)
965965
c.Expr(node.Value)
966966
var op byte
@@ -993,7 +993,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
993993
panic("Unknown BinOp")
994994
}
995995
c.Op(op)
996-
setctx.SetCtx(ast.Store)
996+
setctx.SetCtx(ast.AugStore)
997997
c.Expr(node.Target)
998998
case *ast.For:
999999
// Target Expr
@@ -1118,7 +1118,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
11181118
panic(py.ExceptionNewf(py.SyntaxError, "'continue' not properly in loop"))
11191119
}
11201120
if l.IsForLoop {
1121-
// FIXME when do we use CONTINUE_LOOP?
1121+
// FIXME when do we use CONTINUE_LOOP? - need to port the code from compile.c
11221122
c.Jump(vm.JUMP_ABSOLUTE, l.Start)
11231123
//c.Jump(vm.CONTINUE_LOOP, l.Start)
11241124
} else {
@@ -1183,16 +1183,14 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
11831183
switch optype {
11841184
case OP_DEREF:
11851185
switch ctx {
1186-
case ast.Load:
1186+
case ast.Load, ast.AugLoad:
11871187
if c.SymTable.Type == symtable.ClassBlock {
11881188
op = vm.LOAD_CLASSDEREF
11891189
} else {
11901190
op = vm.LOAD_DEREF
11911191
}
1192-
case ast.Store:
1192+
case ast.Store, ast.AugStore:
11931193
op = vm.STORE_DEREF
1194-
case ast.AugLoad:
1195-
case ast.AugStore:
11961194
case ast.Del:
11971195
op = vm.DELETE_DEREF
11981196
case ast.Param:
@@ -1202,14 +1200,12 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
12021200
}
12031201
case OP_FAST:
12041202
switch ctx {
1205-
case ast.Load:
1203+
case ast.Load, ast.AugLoad:
12061204
op = vm.LOAD_FAST
1207-
case ast.Store:
1205+
case ast.Store, ast.AugStore:
12081206
op = vm.STORE_FAST
12091207
case ast.Del:
12101208
op = vm.DELETE_FAST
1211-
case ast.AugLoad:
1212-
case ast.AugStore:
12131209
case ast.Param:
12141210
panic("NameOp: param invalid for local variable")
12151211
default:
@@ -1218,29 +1214,25 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
12181214
dict = &c.Code.Varnames
12191215
case OP_GLOBAL:
12201216
switch ctx {
1221-
case ast.Load:
1217+
case ast.Load, ast.AugLoad:
12221218
op = vm.LOAD_GLOBAL
1223-
case ast.Store:
1219+
case ast.Store, ast.AugStore:
12241220
op = vm.STORE_GLOBAL
12251221
case ast.Del:
12261222
op = vm.DELETE_GLOBAL
1227-
case ast.AugLoad:
1228-
case ast.AugStore:
12291223
case ast.Param:
12301224
panic("NameOp: param invalid for global variable")
12311225
default:
12321226
panic("NameOp: ctx invalid for global variable")
12331227
}
12341228
case OP_NAME:
12351229
switch ctx {
1236-
case ast.Load:
1230+
case ast.Load, ast.AugLoad:
12371231
op = vm.LOAD_NAME
1238-
case ast.Store:
1232+
case ast.Store, ast.AugStore:
12391233
op = vm.STORE_NAME
12401234
case ast.Del:
12411235
op = vm.DELETE_NAME
1242-
case ast.AugLoad:
1243-
case ast.AugStore:
12441236
case ast.Param:
12451237
panic("NameOp: param invalid for name variable")
12461238
default:
@@ -1403,6 +1395,92 @@ func (c *compiler) tupleOrList(op byte, ctx ast.ExprContext, elts []ast.Expr) {
14031395
}
14041396
}
14051397

1398+
// compile a subscript
1399+
func (c *compiler) subscript(kind string, ctx ast.ExprContext) {
1400+
switch ctx {
1401+
case ast.AugLoad:
1402+
c.Op(vm.DUP_TOP_TWO)
1403+
c.Op(vm.BINARY_SUBSCR)
1404+
case ast.Load:
1405+
c.Op(vm.BINARY_SUBSCR)
1406+
case ast.AugStore:
1407+
c.Op(vm.ROT_THREE)
1408+
c.Op(vm.STORE_SUBSCR)
1409+
case ast.Store:
1410+
c.Op(vm.STORE_SUBSCR)
1411+
case ast.Del:
1412+
c.Op(vm.DELETE_SUBSCR)
1413+
case ast.Param:
1414+
panic(fmt.Sprintf("invalid %v kind %v in subscript", kind, ctx))
1415+
}
1416+
}
1417+
1418+
// build the slice
1419+
func (c *compiler) buildSlice(slice *ast.Slice, ctx ast.ExprContext) {
1420+
n := uint32(2)
1421+
1422+
/* only handles the cases where BUILD_SLICE is emitted */
1423+
if slice.Lower != nil {
1424+
c.Expr(slice.Lower)
1425+
} else {
1426+
c.LoadConst(py.None)
1427+
}
1428+
1429+
if slice.Upper != nil {
1430+
c.Expr(slice.Upper)
1431+
} else {
1432+
c.LoadConst(py.None)
1433+
}
1434+
1435+
if slice.Step != nil {
1436+
n++
1437+
c.Expr(slice.Step)
1438+
}
1439+
c.OpArg(vm.BUILD_SLICE, n)
1440+
}
1441+
1442+
// compile a nested slice
1443+
func (c *compiler) nestedSlice(s ast.Slicer, ctx ast.ExprContext) {
1444+
switch node := s.(type) {
1445+
case *ast.Slice:
1446+
c.buildSlice(node, ctx)
1447+
case *ast.Index:
1448+
c.Expr(node.Value)
1449+
case *ast.ExtSlice:
1450+
panic("extended slice invalid in nested slice")
1451+
default:
1452+
panic("nestedSlice: unknown type")
1453+
}
1454+
}
1455+
1456+
// Compile a slice
1457+
func (c *compiler) slice(s ast.Slicer, ctx ast.ExprContext) {
1458+
kindname := ""
1459+
switch node := s.(type) {
1460+
case *ast.Index:
1461+
kindname = "index"
1462+
if ctx != ast.AugStore {
1463+
c.Expr(node.Value)
1464+
}
1465+
case *ast.Slice:
1466+
kindname = "slice"
1467+
if ctx != ast.AugStore {
1468+
c.buildSlice(node, ctx)
1469+
}
1470+
case *ast.ExtSlice:
1471+
kindname = "extended slice"
1472+
if ctx != ast.AugStore {
1473+
for _, sub := range node.Dims {
1474+
c.nestedSlice(sub, ctx)
1475+
}
1476+
c.OpArg(vm.BUILD_TUPLE, uint32(len(node.Dims)))
1477+
}
1478+
default:
1479+
panic(fmt.Sprintf("invalid subscript kind %T", s))
1480+
}
1481+
c.subscript(kindname, ctx)
1482+
}
1483+
14061484
// Compile expressions
14071485
func (c *compiler) Exprs(exprs []ast.Expr) {
14081486
for _, expr := range exprs {
@@ -1643,14 +1721,51 @@ func (c *compiler) Expr(expr ast.Expr) {
16431721
// Value Expr
16441722
// Attr Identifier
16451723
// Ctx ExprContext
1646-
// FIXME do something with Ctx
1647-
c.Expr(node.Value)
1648-
c.OpArg(vm.LOAD_ATTR, c.Name(node.Attr))
1724+
if node.Ctx != ast.AugStore {
1725+
c.Expr(node.Value)
1726+
}
1727+
var op byte
1728+
switch node.Ctx {
1729+
case ast.AugLoad:
1730+
c.Op(vm.DUP_TOP)
1731+
op = vm.LOAD_ATTR
1732+
case ast.Load:
1733+
op = vm.LOAD_ATTR
1734+
case ast.AugStore:
1735+
c.Op(vm.ROT_TWO)
1736+
op = vm.STORE_ATTR
1737+
case ast.Store:
1738+
op = vm.STORE_ATTR
1739+
case ast.Del:
1740+
op = vm.DELETE_ATTR
1741+
case ast.Param:
1742+
panic("param invalid in attribute expression")
1743+
default:
1744+
panic("unknown context in attribute expression")
1745+
}
1746+
c.OpArg(op, c.Name(node.Attr))
16491747
case *ast.Subscript:
16501748
// Value Expr
16511749
// Slice Slicer
16521750
// Ctx ExprContext
1653-
panic("FIXME compile: Subscript not implemented")
1751+
switch node.Ctx {
1752+
case ast.AugLoad:
1753+
c.Expr(node.Value)
1754+
c.slice(node.Slice, ast.AugLoad)
1755+
case ast.Load:
1756+
c.Expr(node.Value)
1757+
c.slice(node.Slice, ast.Load)
1758+
case ast.AugStore:
1759+
c.slice(node.Slice, ast.AugStore)
1760+
case ast.Store:
1761+
c.Expr(node.Value)
1762+
c.slice(node.Slice, ast.Store)
1763+
case ast.Del:
1764+
c.Expr(node.Value)
1765+
c.slice(node.Slice, ast.Del)
1766+
default:
1767+
panic("param invalid in subscript expression")
1768+
}
16541769
case *ast.Starred:
16551770
// Value Expr
16561771
// Ctx ExprContext

0 commit comments

Comments
 (0)