1

more syntactic sugar

This commit is contained in:
Christoph
2021-09-01 22:49:06 +02:00
parent 9e122d9ce6
commit 4e41cdc724
6 changed files with 115 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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():

View File

@ -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")