From 0317cb731b090e2003d141084c7f04663789bf85 Mon Sep 17 00:00:00 2001 From: Micke Nordin Date: Fri, 17 Jun 2022 17:09:43 +0200 Subject: [PATCH] Functions can now return --- interpreter.py | 4 +++- lexer.py | 59 ++++++++++++++++++++++++++++++++------------------ parser.py | 17 ++++++++++++++- return.mn | 14 ++++++++++++ 4 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 return.mn diff --git a/interpreter.py b/interpreter.py index 674d9a1..9ca0997 100755 --- a/interpreter.py +++ b/interpreter.py @@ -24,9 +24,11 @@ def parse_expression(variable_list, expression, all_tokens): if len(split_on_space) == 1: for param in variable_list: if param['signifier'] == expression: + if type(param['expression']) == type(dict()): + return param['expression']['expression'] match param['type']: case 'string': - return param['expression'] + return str(param['expression']) case 'number': resolved = list() for part in param['expression'].split(' '): diff --git a/lexer.py b/lexer.py index e514aec..48b944a 100755 --- a/lexer.py +++ b/lexer.py @@ -5,6 +5,31 @@ import sys def find(needle: str, haystack: str) -> bool: return haystack.find(needle) != -1 +def parse_lparen(line: str) -> list: + tokens = list() + split_on_lparen = line.split('(') + name = split_on_lparen[0].strip() + if find('=', line): + name = name.split('=')[1].strip() + without_name = '('.join(split_on_lparen[1:]) + split_on_rparen = without_name.split(')') + params_str = ')'.join(split_on_rparen[:-1]) + params = list(map(str.strip,params_str.split(','))) + if name not in ['if', 'while']: + function_call = {"variant": "function_call", "value": name, "params": params, "line_number": lineno} + tokens.append(function_call) + elif name == "if": + conditional = {"variant": "conditional", "value": name, "condition": ','.join(params), "line_number": lineno} + tokens.append(conditional) + expression = {"variant": "start_block", "value": "{", "line_number": lineno} + tokens.append(expression) + else: + loop = {"variant": "loop", "value": name, "condition": ','.join(params), "line_number": lineno} + tokens.append(loop) + expression = {"variant": "start_block", "value": "{", "line_number": lineno} + tokens.append(expression) + return tokens + source: list = list() program = './prog.mn' if len(sys.argv) > 1: @@ -44,14 +69,19 @@ for lineno in range(1, num_lines + 1): signifier = {"variant": "function_declaration", "value": name, "params": params, "line_number": lineno} tokens.append(signifier) if find('=', line): + expressions = list() colon_equals_rhs = '='.join(colon_rhs_split_on_equals[1:]) operator = {"variant": "operator", "value": '=', "line_number": lineno} tokens.append(operator) expr = colon_equals_rhs.strip() - expression = {"variant": "expression", "value": expr, "line_number": lineno} + expressions.append({"variant": "expression", "value": expr, "line_number": lineno}) if expr == '{': - expression = {"variant": "start_block", "value": expr, "line_number": lineno} - tokens.append(expression) + expressions[0] = {"variant": "start_block", "value": expr, "line_number": lineno} + elif find('(', line) and find(')', line): + expressions = parse_lparen(line) + for expression in expressions: + tokens.append(expression) + elif find('=', line): equals_rhs = '='.join(split_on_equals[1:]) signifier = {"variant": "signifier", "value": equals_lhs.strip(), "line_number": lineno} @@ -67,25 +97,12 @@ for lineno in range(1, num_lines + 1): expression = {"variant": "end_block", "value": '}', "line_number": lineno} tokens.append(expression) elif find('(', line): - split_on_lparen = line.split('(') - name = split_on_lparen[0].strip() - without_name = '('.join(split_on_lparen[1:]) - split_on_rparen = without_name.split(')') - params_str = ')'.join(split_on_rparen[:-1]) - params = list(map(str.strip,params_str.split(','))) - if name not in ['if', 'while']: - function_call = {"variant": "function_call", "value": name, "params": params, "line_number": lineno} - tokens.append(function_call) - elif name == "if": - conditional = {"variant": "conditional", "value": name, "condition": ','.join(params), "line_number": lineno} - tokens.append(conditional) - expression = {"variant": "start_block", "value": "{", "line_number": lineno} - tokens.append(expression) - else: - loop = {"variant": "loop", "value": name, "condition": ','.join(params), "line_number": lineno} - tokens.append(loop) - expression = {"variant": "start_block", "value": "{", "line_number": lineno} + for expression in parse_lparen(line): tokens.append(expression) + elif find('return', line): + rhs = line.strip().split()[1] + expression = {"variant": "return", "value": rhs, "line_number": lineno} + tokens.append(expression) else: if line.strip() == '{': expression = {"variant": "start_block", "value": '{', "line_number": lineno} diff --git a/parser.py b/parser.py index 28e4711..c6fbed4 100755 --- a/parser.py +++ b/parser.py @@ -25,6 +25,15 @@ def find_token_indicies(key: str, tokens: list) -> list: index = index + 1 return result +def find_return_statement(maybe_expression, usefull_tokens) -> dict: + expression = dict() + for token in usefull_tokens: + if maybe_expression['value'] == token['signifier'] and token['variant'] == 'function_declaration': + for part in token['body']: + if part['variant'] == 'return_statement': + return part + return expression + def collect_body(index: int, tokens: list) -> list: uncollapsed_tokens = list() token = peek(index + 1, tokens) @@ -86,7 +95,6 @@ def collapse_tokens(uncollapsed_tokens: list) -> list: block_index = -1 block_lineno = -1 - # This is a declaration if token['variant'] == 'syntax_error': if in_block: compare_lineno = block_lineno + 1 @@ -118,6 +126,8 @@ def collapse_tokens(uncollapsed_tokens: list) -> list: if maybe_expression and maybe_expression['variant'] == 'expression': line_number = maybe_expression['line_number'] expression = maybe_expression['value'] + elif maybe_expression and maybe_expression['variant'] == 'function_call': + expression = find_return_statement(maybe_expression, usefull_tokens.copy()) usefull_token = { "variant": "variable_declaration", "signifier": name, "type": token['value'], "line_number": line_number, "expression": expression } usefull_tokens.append(usefull_token) if token['variant'] == 'function_declaration': @@ -131,6 +141,11 @@ def collapse_tokens(uncollapsed_tokens: list) -> list: usefull_token = {"variant": "function_call", "signifier": token['value'], "line_number": token['line_number'], "params": token['params']} usefull_tokens.append(usefull_token) + if token['variant'] == 'return': + for tkn in usefull_tokens.copy(): + if token['value'] == tkn['signifier']: + usefull_token = {"variant": "return_statement", "signifier": tkn['signifier'], "type": tkn['type'], "line_number": tkn['line_number'], "expression": tkn['expression']} + usefull_tokens.append(usefull_token) usefull_tokens.sort(key=operator.itemgetter('line_number')) return usefull_tokens diff --git a/return.mn b/return.mn new file mode 100644 index 0000000..62e0851 --- /dev/null +++ b/return.mn @@ -0,0 +1,14 @@ +func: test(void: i) = { + number: x = 10 + return x +} +func: print(number: n, string: endl) = { + stdout: out = n + stdout: outln = endl +} +string: end = { + +} +void: j = void +number: y = test(j) +print(y, end)