more syntactic sugar
This commit is contained in:
@ -9,6 +9,8 @@ def pass:
|
|||||||
object inttrait:
|
object inttrait:
|
||||||
def eq(other):
|
def eq(other):
|
||||||
self $int_eq(other)
|
self $int_eq(other)
|
||||||
|
def noteq(other):
|
||||||
|
self $int_eq(other) not
|
||||||
|
|
||||||
def leq(other):
|
def leq(other):
|
||||||
self $int_leq(other)
|
self $int_leq(other)
|
||||||
@ -31,6 +33,8 @@ object inttrait:
|
|||||||
self $int_mod(other)
|
self $int_mod(other)
|
||||||
def inc:
|
def inc:
|
||||||
self $int_inc
|
self $int_inc
|
||||||
|
def dec:
|
||||||
|
self $int_dec
|
||||||
|
|
||||||
def tobool:
|
def tobool:
|
||||||
self $int_tobool
|
self $int_tobool
|
||||||
|
@ -33,7 +33,7 @@ class Interpreter(object):
|
|||||||
pc = 0
|
pc = 0
|
||||||
stack = []
|
stack = []
|
||||||
code = bytecode.code
|
code = bytecode.code
|
||||||
print(disassemble(bytecode))
|
# print(disassemble(bytecode))
|
||||||
while pc < len(code):
|
while pc < len(code):
|
||||||
opcode = ord(code[pc]) # convert unicode to number
|
opcode = ord(code[pc]) # convert unicode to number
|
||||||
pc += 1
|
pc += 1
|
||||||
|
@ -27,7 +27,8 @@ class ObjectSpace(object):
|
|||||||
import os
|
import os
|
||||||
builtins = os.path.join(
|
builtins = os.path.join(
|
||||||
os.path.dirname(__file__),
|
os.path.dirname(__file__),
|
||||||
'../builtins.simple')
|
'..',
|
||||||
|
'builtins.simple')
|
||||||
with open(builtins, 'r') as f:
|
with open(builtins, 'r') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
@ -106,6 +106,11 @@ def simple_int_increment(a):
|
|||||||
return a + 1
|
return a + 1
|
||||||
|
|
||||||
|
|
||||||
|
@primitive("int_dec", [int], int)
|
||||||
|
def simple_int_decrement(a):
|
||||||
|
return a - 1
|
||||||
|
|
||||||
|
|
||||||
@primitive("int_tobool", [int], bool)
|
@primitive("int_tobool", [int], bool)
|
||||||
def simple_int_tobool(a):
|
def simple_int_tobool(a):
|
||||||
return a
|
return a
|
||||||
|
@ -174,8 +174,25 @@ Minus = r'-'
|
|||||||
Multiply = r'\*'
|
Multiply = r'\*'
|
||||||
Divide = r'/'
|
Divide = r'/'
|
||||||
Increment = r'\+\+'
|
Increment = r'\+\+'
|
||||||
|
Decrement = r'--'
|
||||||
Modulo = r'%'
|
Modulo = r'%'
|
||||||
|
|
||||||
|
PlusInplace = r'\+='
|
||||||
|
MinusInplace = r'-='
|
||||||
|
MultiplyInplace = r'\*='
|
||||||
|
DivideInplace = r'/='
|
||||||
|
|
||||||
|
Less = r'<'
|
||||||
|
LessEqual = r'<='
|
||||||
|
Greater = r'>'
|
||||||
|
GreaterEqual = r'>='
|
||||||
|
Equal = r'=='
|
||||||
|
NotEqual = r'!='
|
||||||
|
|
||||||
|
And = r'&&'
|
||||||
|
Or = r'\|\|'
|
||||||
|
Not = r'!'
|
||||||
|
|
||||||
GC = r'gc'
|
GC = r'gc'
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
@ -191,9 +208,13 @@ tokens = ["If", "Else", "While", "Def", "Object", "Ignore",
|
|||||||
"String", "Boolean", "Double",
|
"String", "Boolean", "Double",
|
||||||
"Number", # after Double
|
"Number", # after Double
|
||||||
"GC",
|
"GC",
|
||||||
"NewlineAndWhitespace", "OpenBracket", "CloseBracket", "Comma", "Assign", "Colon",
|
"NewlineAndWhitespace", "OpenBracket", "CloseBracket", "Comma", "Colon",
|
||||||
|
"And", "Or", "LessEqual", "Less", "GreaterEqual", "Greater", "Equal", "NotEqual",
|
||||||
|
"Decrement", "PlusInplace", "MinusInplace", "MultiplyInplace", "DivideInplace",
|
||||||
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo",
|
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo",
|
||||||
"Name", "PrimitiveName"]
|
"Assign", "Not",
|
||||||
|
"Name", "PrimitiveName",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def make_lexer():
|
def make_lexer():
|
||||||
|
@ -9,13 +9,23 @@ pg = ParserGenerator(["If", "Else", "While", "Def", "Object", "Number",
|
|||||||
"String", "Boolean", "Double",
|
"String", "Boolean", "Double",
|
||||||
"GC",
|
"GC",
|
||||||
"Name", "Indent", "Dedent", "Newline", "OpenBracket",
|
"Name", "Indent", "Dedent", "Newline", "OpenBracket",
|
||||||
"CloseBracket", "Comma", "Assign", "Colon",
|
"CloseBracket", "Comma", "Colon",
|
||||||
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo",
|
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo",
|
||||||
"PrimitiveName", "EOF"],
|
"Decrement", "PlusInplace", "MinusInplace", "MultiplyInplace", "DivideInplace",
|
||||||
|
"Less", "LessEqual", "Greater", "GreaterEqual", "Equal", "NotEqual",
|
||||||
|
"Assign",
|
||||||
|
"And", "Or",
|
||||||
|
"PrimitiveName", "EOF",
|
||||||
|
"Not"],
|
||||||
# Operator precedence for ambiguous rules, ascending
|
# Operator precedence for ambiguous rules, ascending
|
||||||
precedence=[("left", ["Plus", "Minus"]),
|
precedence=[("left", ["Or"]),
|
||||||
|
("left", ["And"]),
|
||||||
|
("left", ["Equal", "NotEqual"]),
|
||||||
|
("left", ["Less", "LessEqual", "Greater", "GreaterEqual"]),
|
||||||
|
("left", ["Plus", "Minus"]),
|
||||||
("left", ["Multiply", "Divide", "Modulo"]),
|
("left", ["Multiply", "Divide", "Modulo"]),
|
||||||
("left", ["Increment"])])
|
("left", ["Not"]),
|
||||||
|
("left", ["Increment", "Decrement"])])
|
||||||
|
|
||||||
|
|
||||||
def build_methodcall(call, cls, receiver=None):
|
def build_methodcall(call, cls, receiver=None):
|
||||||
@ -103,7 +113,6 @@ def objectstatement(obj):
|
|||||||
if len(obj) == 3:
|
if len(obj) == 3:
|
||||||
blk = obj[2]
|
blk = obj[2]
|
||||||
else:
|
else:
|
||||||
print(obj)
|
|
||||||
parents = obj[2] # list of assignments (simpleast.Assignment)
|
parents = obj[2] # list of assignments (simpleast.Assignment)
|
||||||
names = [p.attrname for p in parents]
|
names = [p.attrname for p in parents]
|
||||||
expressions = [p.expression for p in parents]
|
expressions = [p.expression for p in parents]
|
||||||
@ -168,22 +177,76 @@ def expression(expr):
|
|||||||
@pg.production("expression : expression Multiply expression")
|
@pg.production("expression : expression Multiply expression")
|
||||||
@pg.production("expression : expression Divide expression")
|
@pg.production("expression : expression Divide expression")
|
||||||
@pg.production("expression : expression Modulo expression")
|
@pg.production("expression : expression Modulo expression")
|
||||||
@pg.production("expression : expression Increment expression")
|
def sugar_binary_arithmetic(expr):
|
||||||
@pg.production("expression : expression Increment")
|
|
||||||
def sugar(expr):
|
|
||||||
op = {
|
op = {
|
||||||
"Plus": "$int_add",
|
"Plus": "add",
|
||||||
"Minus": "$int_sub",
|
"Minus": "sub",
|
||||||
"Multiply": "$int_mul",
|
"Multiply": "mul",
|
||||||
"Divide": "$int_div",
|
"Divide": "div",
|
||||||
"Modulo": "$int_mod",
|
"Modulo": "mod",
|
||||||
"Increment": "$int_inc"
|
|
||||||
}[expr[1].name]
|
}[expr[1].name]
|
||||||
|
|
||||||
if len(expr) == 2: # unary operator
|
return build_methodcall([op, [expr[2]]], simpleast.MethodCall, expr[0]) # ([name, arg], class, receiver)
|
||||||
return build_methodcall([op, []], simpleast.PrimitiveMethodCall, expr[0]) # ([name, arg], class, receiver)
|
|
||||||
|
|
||||||
return build_methodcall([op, [expr[2]]], simpleast.PrimitiveMethodCall, expr[0])
|
|
||||||
|
@pg.production("expression : expression Decrement expression")
|
||||||
|
@pg.production("expression : expression Decrement")
|
||||||
|
@pg.production("expression : expression Increment expression")
|
||||||
|
@pg.production("expression : expression Increment")
|
||||||
|
@pg.production("expression : expression PlusInplace expression")
|
||||||
|
@pg.production("expression : expression MinusInplace expression")
|
||||||
|
@pg.production("expression : expression MultiplyInplace expression")
|
||||||
|
@pg.production("expression : expression DivideInplace expression")
|
||||||
|
def sugar_inplace_arithmetic(expr):
|
||||||
|
op = {
|
||||||
|
"Increment": "inc",
|
||||||
|
"Decrement": "dec",
|
||||||
|
"PlusInplace": "add",
|
||||||
|
"MinusInplace": "sub",
|
||||||
|
"MultiplyInplace": "mul",
|
||||||
|
"DivideInplace": "div",
|
||||||
|
}[expr[1].name]
|
||||||
|
args = [] if len(expr) == 2 else [expr[2]] # unary/binary
|
||||||
|
methcall = build_methodcall([op, args], simpleast.MethodCall, expr[0])
|
||||||
|
|
||||||
|
if isinstance(expr[0], simpleast.MethodCall) and expr[0].arguments == []: # attribute
|
||||||
|
return simpleast.Assignment(expr[0].receiver, expr[0].methodname, methcall) # modify inplace
|
||||||
|
|
||||||
|
return build_methodcall([op, args], simpleast.MethodCall, expr[0]) # just increment
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("expression : expression Less expression")
|
||||||
|
@pg.production("expression : expression LessEqual expression")
|
||||||
|
@pg.production("expression : expression Greater expression")
|
||||||
|
@pg.production("expression : expression GreaterEqual expression")
|
||||||
|
@pg.production("expression : expression Equal expression")
|
||||||
|
@pg.production("expression : expression NotEqual expression")
|
||||||
|
def sugar_comparison(expr):
|
||||||
|
op = {
|
||||||
|
"Less": "less",
|
||||||
|
"LessEqual": "leq",
|
||||||
|
"Greater": "greater",
|
||||||
|
"GreaterEqual": "geq",
|
||||||
|
"Equal": "eq",
|
||||||
|
"NotEqual": "noteq",
|
||||||
|
}[expr[1].name]
|
||||||
|
|
||||||
|
return build_methodcall([op, [expr[2]]], simpleast.MethodCall, expr[0]) # ([name, arg], class, receiver)
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("expression : expression And expression")
|
||||||
|
@pg.production("expression : expression Or expression")
|
||||||
|
@pg.production("expression : Not expression")
|
||||||
|
def sugar_logical(expr):
|
||||||
|
if len(expr) == 2: # unary
|
||||||
|
return build_methodcall(["not", []], simpleast.MethodCall, expr[1])
|
||||||
|
|
||||||
|
op = {
|
||||||
|
"And": "and",
|
||||||
|
"Or": "or",
|
||||||
|
}[expr[1].name]
|
||||||
|
|
||||||
|
return build_methodcall([op, [expr[2]]], simpleast.MethodCall, expr[0]) # ([name, arg], class, receiver)
|
||||||
|
|
||||||
|
|
||||||
@pg.production("expression : OpenBracket expression CloseBracket")
|
@pg.production("expression : OpenBracket expression CloseBracket")
|
||||||
|
Reference in New Issue
Block a user