def parse_call_expression(self): recv = self.parse_atomic_expression() while True: is_async = False if self.at_punctuation('->'): self.expect_punctuation('->') is_async = True elif self.at_punctuation('.'): self.expect_punctuation('.') if self.at_punctuation('('): selector = Parser._SAUSAGES start = '(' end = ')' elif self.at_punctuation('['): selector = Parser._SQUARE_SAUSAGES start = '[' end = ']' else: break prefix = [ ast.Argument(data._SUBJECT, recv), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] rest = self.parse_arguments(start, end) recv = ast.Invocation(prefix + rest) return recv
def parse_atomic_expression(self): if self.at_type(Token.LITERAL): value = self.expect_type(Token.LITERAL) result = ast.Literal(value) if isinstance(value, data.DecimalFraction): # While the infrastructure is not in place to create floats without # magic we insert a new_float invocation in the parser. result = ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["ctrino"])))), ast.Argument(data._SELECTOR, ast.Literal(data.Operation.infix("new_float_32"))), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, result) ]) return result elif self.at_type(Token.IDENTIFIER): return self.parse_variable() elif self.at_punctuation('('): self.expect_punctuation('(') result = self.parse_expression(False) self.expect_punctuation(')') return result elif self.at_punctuation('['): return self.parse_array_expression() elif self.at_punctuation('{'): return self.parse_sequence_expression() elif self.at_word('null'): self.expect_word('null') return ast.Literal(None) elif self.at_word('true'): self.expect_word('true') return ast.Literal(True) elif self.at_word('false'): self.expect_word('false') return ast.Literal(False) elif self.at_word('subject'): self.expect_word('subject') return ast.Literal(data._SUBJECT) elif self.at_word('selector'): self.expect_word('selector') return ast.Literal(data._SELECTOR) elif self.at_word('transport'): self.expect_word('transport') return ast.Literal(data._TRANSPORT) elif self.at_word('async'): self.expect_word('async') return ast.Literal(data._ASYNC) elif self.at_word('sync'): self.expect_word('sync') return ast.Literal(data._SYNC) elif self.at_word('module'): self.expect_word('module') return ast.CurrentModule() elif self.at_type(Token.QUOTE): return self.parse_quote() else: raise self.new_syntax_error()
def parse_operator_expression(self): left = self.parse_unary_expression() while self.at_type(Token.OPERATION): (selector, is_async, rest) = self.parse_operator_tail() prefix = [ ast.Argument(data._SUBJECT, left), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] left = ast.Invocation(prefix + rest) return left
def parse_new_expression(self, expect_delim): self.expect_word('new') cons = self.parse_atomic_expression() args = self.parse_arguments('(', ')') self.expect_statement_delimiter(expect_delim) prefix = [ ast.Argument(data._SUBJECT, cons), ast.Argument(data._SELECTOR, ast.Literal(Parser._NEW)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)) ] return ast.Invocation(prefix + args)
def parse_unary_expression(self): if self.at_type(Token.OPERATION): (name, is_async) = self.expect_type(Token.OPERATION) selector = data.Operation.prefix(name) subject = self.parse_unary_expression() args = [ ast.Argument(data._SUBJECT, subject), ast.Argument(data._SELECTOR, ast.Literal(selector)), ast.Argument(data._TRANSPORT, ast.Literal(data._ASYNC if is_async else data._SYNC)) ] return ast.Invocation(args) else: return self.parse_call_expression()
def parse_for_expression(self, expect_delim): self.expect_word('for') sig = self.parse_signature() self.expect_word('in') elms = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) thunk = ast.Lambda([ast.Method(sig, body)]) return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "for"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, elms), ast.Argument(1, thunk), ])
def parse_while_expression(self, expect_delim): self.expect_word('while') cond = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) methods = [ ast.Lambda.method(cond, data.Operation.infix('keep_running?')), ast.Lambda.method(body, data.Operation.infix('run!')) ] return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "while"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, ast.Lambda(methods)), ])
def parse_when_expression(self, expect_delim): self.expect_word('when') self.expect_word('def') sig = self.parse_signature() self.expect_punctuation(':=') value = self.parse_expression(False) self.expect_word('do') body = self.parse_expression(expect_delim) thunk = ast.Lambda([ast.Method(sig, body)]) return ast.Invocation([ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "when_def"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, value), ast.Argument(1, thunk), ])
def parse_if_expression(self, expect_delim): self.expect_word('if') cond = self.parse_expression(False) self.expect_word('then') then_part = self.parse_expression(expect_delim) if self.at_word('else'): self.expect_word('else') else_part = self.parse_expression(expect_delim) else: else_part = ast.Literal(None) methods = [ ast.Lambda.method(then_part, data.Operation.infix('then!')), ast.Lambda.method(else_part, data.Operation.infix('else!')) ] args = [ ast.Argument(data._SUBJECT, ast.Variable(data.Identifier(-1, data.Path(["core", "if"])))), ast.Argument(data._SELECTOR, ast.Literal(Parser._SAUSAGES)), ast.Argument(data._TRANSPORT, ast.Literal(data._SYNC)), ast.Argument(0, cond), ast.Argument(1, ast.Lambda(methods)) ] result = ast.Invocation(args) return result