* Implemented the desugaring pass, except for exception support; also badly needs cleanup of dead code
* Pass through metadata to end of desugaring phase (for error reporting)
* Pass through more metadata, package it at tokenization phase
* Added error handling to desugared code
* Add line numbers to function call errors, clean up
* Delete dead code
import collections
+import parsing
+
+DesugaredFunctionCallExpression = collections.namedtuple(
+ 'DesugaredFunctionCallExpression',
+ (
+ 'metadata',
+ 'function',
+ 'argument_list',
+ ),
+)
+
+DesugaredIfExpression = collections.namedtuple(
+ 'DesugaredIfExpression',
+ (
+ 'condition_expression',
+ 'if_statement_list',
+ 'else_statement_list',
+ ),
+)
+
+DesugaredIntegerLiteralExpression = collections.namedtuple(
+ 'DesugaredIntegerLiteralExpression',
+ (
+ 'integer',
+ ),
+)
+
+DesugaredListLiteralExpression = collections.namedtuple(
+ 'DesugaredListLiteralExpression',
+ (
+ 'item_expression_list',
+ ),
+)
+
+DesugaredStringLiteralExpression = collections.namedtuple(
+ 'DesugaredStringLiteralExpression',
+ (
+ 'string',
+ ),
+)
+
+DesugaredSymbolExpressionPair = collections.namedtuple(
+ 'DesugaredSymbolExpressionPair',
+ (
+ 'symbol',
+ 'expression',
+ ),
+)
+
+DesugaredStructureLiteralExpression = collections.namedtuple(
+ 'DesugaredStructureLiteralExpression',
+ (
+ 'fields',
+ ),
+)
+
+DesugaredSymbolExpression = collections.namedtuple(
+ 'DesugaredSymbolExpression',
+ (
+ 'metadata',
+ 'symbol',
+ ),
+)
+
+DesugaredAssignmentStatement = collections.namedtuple(
+ 'DesugaredAssignmentStatement',
+ (
+ 'target',
+ 'expression',
+ ),
+)
+
+DesugaredExpressionStatement = collections.namedtuple(
+ 'DesugaredExpressionStatement',
+ (
+ 'expression',
+ ),
+)
+
+DesugaredFunctionDefinitionStatement = collections.namedtuple(
+ 'DesugaredFunctionDefinitionStatement',
+ (
+ 'name',
+ 'argument_name_list',
+ 'statement_list',
+ ),
+)
+
DesugaredProgram = collections.namedtuple(
'DesugaredProgram',
(
),
)
+def desugar_function_call_expression(expression):
+ return DesugaredFunctionCallExpression(
+ metadata=expression.metadata,
+ function=desugar_expression(expression.function),
+ argument_list=tuple(desugar_expression(e) for e in expression.arguments),
+ )
+
+def desugar_if_expression(expression):
+ return DesugaredIfExpression(
+ condition_expression=desugar_expression(expression.condition_expression),
+ if_statement_list=tuple(desugar_statement(s) for s in expression.if_statement_list),
+ else_statement_list=tuple(desugar_statement(s) for s in expression.else_statement_list),
+ )
+
+def desugar_infix_expression(expression):
+ if expression.operator == 'and':
+ return DesugaredIfExpression(
+ condition_expression=desugar_expression(expression.left),
+ if_statement_list=(
+ DesugaredExpressionStatement(expression=desugar_expression(expression.right)),
+ ),
+ else_statement_list=(
+ DesugaredExpressionStatement(
+ expression=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol='false',
+ ),
+ ),
+ ),
+ )
+
+ if expression.operator == 'or':
+ return DesugaredIfExpression(
+ condition_expression=desugar_expression(expression.left),
+ if_statement_list=(
+ DesugaredExpressionStatement(
+ expression=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol='true',
+ ),
+ ),
+ ),
+ else_statement_list=(
+ DesugaredExpressionStatement(expression=desugar_expression(expression.right)),
+ ),
+ )
+
+ if expression.operator == '.':
+ return DesugaredFunctionCallExpression(
+ metadata=expression.metadata,
+ function=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol='__field__',
+ ),
+ argument_list=(
+ desugar_expression(expression.left),
+ DesugaredStringLiteralExpression(string=expression.right.symbol),
+ ),
+ )
+
+ function = {
+ '++': '__concat__',
+ '+': '__add__',
+ '-': '__subtract__',
+ '*': '__multiply__',
+ '//': '__integer_divide__',
+ '%': '__modular_divide__',
+ '<': '__lt__',
+ '>': '__gt__',
+ '<=': '__lte__',
+ '>=': '__gte__',
+ '==': '__eq__',
+ '!=': '__neq__',
+ }[expression.operator]
+
+ return DesugaredFunctionCallExpression(
+ metadata=expression.metadata,
+ function=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol=function,
+ ),
+ argument_list=(
+ desugar_expression(expression.left),
+ desugar_expression(expression.right),
+ ),
+ )
+
+def desugar_integer_literal_expression(expression):
+ return DesugaredIntegerLiteralExpression(
+ integer=expression.integer,
+ )
+
+def desugar_list_item_expression(expression):
+ return DesugaredFunctionCallExpression(
+ metadata=expression.metadata,
+ function=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol='__get__',
+ ),
+ argument_list=(
+ desugar_expression(expression.list_expression),
+ desugar_expression(expression.index_expression),
+ ),
+ )
+
+def desugar_list_literal_expression(expression):
+ return DesugaredListLiteralExpression(
+ item_expression_list=tuple(desugar_expression(i) for i in expression.item_expression_list),
+ )
+
+def desugar_negation_expression(expression):
+ return DesugaredFunctionCallExpression(
+ metadata=expression.metadata,
+ function=DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol='__negate__',
+ ),
+ argument_list=(
+ desugar_expression(expression.value),
+ ),
+ )
+
+def desugar_string_literal_expression(expression):
+ return DesugaredStringLiteralExpression(
+ string=expression.string,
+ )
+
+def desugar_structure_literal_expression(expression):
+ return DesugaredStructureLiteralExpression(
+ fields=tuple(
+ DesugaredSymbolExpressionPair(
+ symbol=p.symbol,
+ expression=desugar_expression(p.expression),
+ ) for p in expression.fields
+ ),
+ )
+
+def desugar_symbol_expression(expression):
+ return DesugaredSymbolExpression(
+ metadata=expression.metadata,
+ symbol=expression.symbol,
+ )
+
+def desugar_expression(expression):
+ return {
+ parsing.FurFunctionCallExpression: desugar_function_call_expression,
+ parsing.FurIfExpression: desugar_if_expression,
+ parsing.FurInfixExpression: desugar_infix_expression,
+ parsing.FurIntegerLiteralExpression: desugar_integer_literal_expression,
+ parsing.FurListItemExpression: desugar_list_item_expression,
+ parsing.FurListLiteralExpression: desugar_list_literal_expression,
+ parsing.FurNegationExpression: desugar_negation_expression,
+ parsing.FurStringLiteralExpression: desugar_string_literal_expression,
+ parsing.FurStructureLiteralExpression: desugar_structure_literal_expression,
+ parsing.FurSymbolExpression: desugar_symbol_expression,
+ }[type(expression)](expression)
+
+def desugar_assignment_statement(statement):
+ return DesugaredAssignmentStatement(
+ target=statement.target,
+ expression=desugar_expression(statement.expression),
+ )
+
+def desugar_expression_statement(statement):
+ return DesugaredExpressionStatement(
+ expression=desugar_expression(statement.expression),
+ )
+
+def desugar_function_definition_statement(statement):
+ return DesugaredFunctionDefinitionStatement(
+ name=statement.name,
+ argument_name_list=statement.argument_name_list,
+ statement_list=tuple(desugar_statement(s) for s in statement.statement_list),
+ )
+
+def desugar_statement(statement):
+ return {
+ parsing.FurAssignmentStatement: desugar_assignment_statement,
+ parsing.FurExpressionStatement: desugar_expression_statement,
+ parsing.FurFunctionDefinitionStatement: desugar_function_definition_statement,
+ }[type(statement)](statement)
+
def desugar(program):
return DesugaredProgram(
- statement_list=program.statement_list,
+ statement_list=[desugar_statement(s) for s in program.statement_list],
)
DivisionByZeroError on line 2
- in get_divided_answer
+ in get_divided_answer on line 5
in __main__
def generate_variable_expression(expression):
return expression.variable
-def generate_function_call_for_fur_infix_operator(expression):
- return 'operator${}(stack, jump, {})'.format(
- expression.name,
- expression.metadata.line,
- )
-
def generate_structure_literal_expression(expression):
return 'Structure_construct({}, {}, {})'.format(
expression.field_count,
expression.value_list_variable,
)
-def generate_dot_expression(expression):
- return 'Structure_get(&{}, SYMBOL_LIST[{}] /* symbol: "{}" */)'.format(
- generate_variable_expression(expression.instance),
- expression.symbol_list_index,
- expression.symbol,
- )
-
def generate_list_construct_expression(expression):
return 'List_construct({})'.format(expression.allocate)
def generate_expression(expression):
return {
- transformation.CDotExpression: generate_dot_expression,
transformation.CFunctionCallExpression: generate_function_call,
- transformation.CFunctionCallForFurInfixOperator: generate_function_call_for_fur_infix_operator,
transformation.CIntegerLiteral: generate_integer_literal,
transformation.CListConstructExpression: generate_list_construct_expression,
transformation.CListGetExpression: generate_list_get_expression,
- transformation.CNegationExpression: generate_negation_expression,
transformation.CStringLiteral: generate_string_literal,
transformation.CStructureLiteralExpression: generate_structure_literal_expression,
transformation.CSymbolExpression: generate_symbol_expression,
transformation.CVariableExpression: generate_variable_expression,
}[type(expression)](expression)
-def generate_negation_expression(c_negation_expression):
- return 'operator$negate({})'.format(
- generate_expression(c_negation_expression.value)
- )
-
def generate_function_call(function_call):
# This gets called twice, so we want to be sure it is efficient and without side effects
assert isinstance(function_call.function_expression, transformation.CVariableExpression)
# TODO Check the type of the things being called
function_expression = generate_variable_expression(function_call.function_expression)
- return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, stack, jump)'.format(
+ return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, stack, {}, jump)'.format(
function_expression,
function_expression,
function_call.argument_count,
+ function_call.metadata.line,
)
def generate_expression_statement(statement):
import collections
-import parsing
+import desugaring
import util
NormalVariableExpression = collections.namedtuple(
],
)
-NormalNegationExpression = collections.namedtuple(
- 'NormalNegationExpression',
- [
- 'internal_expression',
- ],
-)
-
-NormalDotExpression = collections.namedtuple(
- 'NormalDotExpression',
- [
- 'instance',
- 'field',
- ],
-)
-
-NormalInfixExpression = collections.namedtuple(
- 'NormalInfixExpression',
- [
- 'metadata',
- 'order',
- 'operator',
- ],
-)
-
NormalPushStatement = collections.namedtuple(
'NormalPushStatement',
(
NormalFunctionCallExpression = collections.namedtuple(
'NormalFunctionCallExpression',
[
+ 'metadata',
'function_expression',
'argument_count',
],
],
)
-def fake_normalization(counter, thing):
- return (counter, (), thing)
-
def normalize_integer_literal_expression(counter, expression):
variable = '${}'.format(counter)
return (
)
def normalize_function_call_expression(counter, expression):
- assert isinstance(expression, parsing.FurFunctionCallExpression)
-
prestatements = []
- for argument in expression.arguments:
+ for argument in expression.argument_list:
counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
for s in argument_prestatements:
NormalVariableInitializationStatement(
variable=result_variable,
expression=NormalFunctionCallExpression(
+ metadata=expression.metadata,
function_expression=function_expression,
- argument_count=len(expression.arguments),
+ argument_count=len(expression.argument_list),
),
)
)
NormalVariableExpression(variable=result_variable),
)
-def normalize_basic_infix_operation(counter, expression):
- counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
- counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
-
- center_variable = '${}'.format(counter)
- counter += 1
-
- root_prestatements = (
- NormalPushStatement(expression=left_expression),
- NormalPushStatement(expression=right_expression),
- NormalVariableInitializationStatement(
- variable=center_variable,
- expression=NormalInfixExpression(
- metadata=expression.metadata,
- order=expression.order,
- operator=expression.operator,
- ),
- ),
- )
-
- return (
- counter,
- left_prestatements + right_prestatements + root_prestatements,
- NormalVariableExpression(variable=center_variable),
- )
-
-def desugar_ternary_comparison(counter, expression):
- counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left)
- counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right)
-
- left_variable = '${}'.format(counter)
- counter += 1
- middle_variable = '${}'.format(counter)
- counter += 1
-
- # TODO Is there a memory leak if the middle expression throws an exception because the first expression result hasn't been added to the stack?
- juncture_prestatements = (
- NormalVariableInitializationStatement(
- variable=left_variable,
- expression=left_expression,
- ),
- NormalVariableInitializationStatement(
- variable=middle_variable,
- expression=middle_expression,
- )
- )
-
- counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression(
- counter,
- parsing.FurInfixExpression(
- metadata=expression.left.metadata,
- order='and_level',
- operator='and',
- left=parsing.FurInfixExpression(
- metadata=expression.left.metadata,
- order='comparison_level',
- operator=expression.left.operator,
- left=NormalVariableExpression(variable=left_variable),
- right=NormalVariableExpression(variable=middle_variable),
- ),
- right=parsing.FurInfixExpression(
- metadata=expression.metadata,
- order='comparison_level',
- operator=expression.operator,
- left=NormalVariableExpression(variable=middle_variable),
- right=expression.right,
- ),
- )
- )
-
- return (
- counter,
- left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements,
- boolean_expression,
- )
-
-def normalize_comparison_expression(counter, expression):
- if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
- return desugar_ternary_comparison(counter, expression)
-
- return normalize_basic_infix_operation(counter, expression)
-
-def normalize_boolean_expression(counter, expression):
- counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
- counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
-
- result_variable = '${}'.format(counter)
- if_else_prestatment = NormalVariableInitializationStatement(
- variable=result_variable,
- expression=left_expression,
- )
- counter += 1
-
- condition_expression=NormalVariableExpression(variable=result_variable)
- short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
-
- if expression.operator == 'and':
- if_else_statement = NormalIfElseStatement(
- condition_expression=condition_expression,
- if_statement_list=short_circuited_statements,
- else_statement_list=(),
- )
-
- elif expression.operator == 'or':
- if_else_statement = NormalIfElseStatement(
- condition_expression=condition_expression,
- if_statement_list=(),
- else_statement_list=short_circuited_statements,
- )
-
- else:
- raise Exception('Unable to handle operator "{}"'.format(expression.operator))
-
- return (
- counter,
- left_prestatements + (if_else_prestatment, if_else_statement),
- NormalVariableExpression(variable=result_variable),
- )
-
-def normalize_dot_expression(counter, expression):
- assert isinstance(expression.right, parsing.FurSymbolExpression)
-
- counter, prestatements, left_expression = normalize_expression(counter, expression.left)
-
- variable = '${}'.format(counter)
-
- dot_expression_prestatement = NormalVariableInitializationStatement(
- variable=variable,
- expression=NormalDotExpression(
- instance=left_expression,
- field=expression.right.symbol,
- ),
- )
-
- return (
- counter + 1,
- prestatements + (dot_expression_prestatement,),
- NormalVariableExpression(variable=variable),
- )
-
-def normalize_infix_expression(counter, expression):
- return {
- 'multiplication_level': normalize_basic_infix_operation,
- 'addition_level': normalize_basic_infix_operation,
- 'comparison_level': normalize_comparison_expression,
- 'dot_level': normalize_dot_expression,
- 'and_level': normalize_boolean_expression,
- 'or_level': normalize_boolean_expression,
- }[expression.order](counter, expression)
-
def normalize_if_expression(counter, expression):
counter, condition_prestatements, condition_expression = normalize_expression(
counter,
NormalVariableExpression(variable=result_variable),
)
-def normalize_negation_expression(counter, expression):
- counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
-
- internal_variable = '${}'.format(counter)
- counter += 1
-
- return (
- counter,
- prestatements + (
- NormalVariableInitializationStatement(
- variable=internal_variable,
- expression=internal_expression,
- ),
- ),
- NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
- )
-
def normalize_expression(counter, expression):
return {
- NormalInfixExpression: fake_normalization,
- NormalVariableExpression: fake_normalization,
- parsing.FurFunctionCallExpression: normalize_function_call_expression,
- parsing.FurIfExpression: normalize_if_expression,
- parsing.FurInfixExpression: normalize_infix_expression,
- parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
- parsing.FurListLiteralExpression: normalize_list_literal_expression,
- parsing.FurListItemExpression: normalize_list_item_expression,
- parsing.FurNegationExpression: normalize_negation_expression,
- parsing.FurStringLiteralExpression: normalize_string_literal_expression,
- parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
- parsing.FurSymbolExpression: normalize_symbol_expression,
+ desugaring.DesugaredFunctionCallExpression: normalize_function_call_expression,
+ desugaring.DesugaredIfExpression: normalize_if_expression,
+ desugaring.DesugaredIntegerLiteralExpression: normalize_integer_literal_expression,
+ desugaring.DesugaredListLiteralExpression: normalize_list_literal_expression,
+ desugaring.DesugaredStringLiteralExpression: normalize_string_literal_expression,
+ desugaring.DesugaredStructureLiteralExpression: normalize_structure_literal_expression,
+ desugaring.DesugaredSymbolExpression: normalize_symbol_expression,
}[type(expression)](counter, expression)
def normalize_expression_statement(counter, statement):
def normalize_statement(counter, statement):
return {
- parsing.FurAssignmentStatement: normalize_assignment_statement,
- parsing.FurExpressionStatement: normalize_expression_statement,
- parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
+ desugaring.DesugaredAssignmentStatement: normalize_assignment_statement,
+ desugaring.DesugaredExpressionStatement: normalize_expression_statement,
+ desugaring.DesugaredFunctionDefinitionStatement: normalize_function_definition_statement,
}[type(statement)](counter, statement)
@util.force_generator(tuple)
return result_parser
-NodeMetadata = collections.namedtuple(
- 'NodeMetadata',
- [
- 'index',
- 'line',
- ],
-)
-
FurIntegerLiteralExpression = collections.namedtuple(
'FurIntegerLiteralExpression',
[
FurSymbolExpression = collections.namedtuple(
'FurSymbolExpression',
[
+ 'metadata',
'symbol',
],
)
FurNegationExpression = collections.namedtuple(
'FurNegationExpression',
[
+ 'metadata',
'value',
],
)
def _symbol_expression_parser(index, tokens):
if tokens[index].type == 'symbol':
- return (True, index + 1, FurSymbolExpression(symbol=tokens[index].match))
+ return (
+ True,
+ index + 1,
+ FurSymbolExpression(
+ metadata=tokens[index].metadata,
+ symbol=tokens[index].match,
+ ),
+ )
return (False, index, None)
if tokens[index].match != '-':
return failure
+ metadata = tokens[index].metadata
+
success, index, value = _dot_expression_parser(index + 1, tokens)
if not success:
return failure
- return (True, index, FurNegationExpression(value=value))
+ return (True, index, FurNegationExpression(metadata=metadata, value=value))
def _negation_level_expression_parser(index, tokens):
return _or_parser(
if success:
result = FurInfixExpression(
- metadata=NodeMetadata(
- index=tokens[index].index,
- line=tokens[index].line,
- ),
+ metadata=tokens[index].metadata,
order=order,
operator=tokens[index].match,
left=result,
'FurListItemExpression',
[
'list_expression',
+ 'metadata',
'index_expression',
],
)
FurFunctionCallExpression = collections.namedtuple(
'FurFunctionCallExpression',
[
+ 'metadata',
'function',
'arguments',
],
if not success:
return failure
+ metadata = tokens[index].metadata
+
success, index, index_expression = _bracket_wrapped_parser(_expression_parser)(
index,
tokens,
# We can't give this a better name without a bunch of checks, however.
list_expression = FurListItemExpression(
list_expression=list_expression,
+ metadata=metadata,
index_expression=index_expression,
)
+ metadata = tokens[index].metadata
+
success, index, index_expression = _bracket_wrapped_parser(_expression_parser)(
index,
tokens,
if not success:
return failure
+ metadata = tokens[index].metadata
+
success, index, arguments = _parenthese_wrapped_parser(_comma_separated_expression_list_parser)(
index,
tokens,
# "function" is actually the full function call if the next parse attempt doesn't succeed
# We can't give this a better name without a bunch of checks, however.
function = FurFunctionCallExpression(
+ metadata=metadata,
function=function,
arguments=arguments,
)
+ metadata = tokens[index].metadata
+
success, index, arguments = _parenthese_wrapped_parser(_comma_separated_expression_list_parser)(
index,
tokens,
if tokens[index].type == 'symbol':
target = tokens[index].match
- target_assignment_line = tokens[index].line
+ target_assignment_line = tokens[index].metadata.line
index += 1
else:
Environment* environment,
size_t argc,
Stack* stack,
+ const unsigned long line,
jmp_buf parentJump)
{
environment = Environment_construct(environmentPool, environment);
jmp_buf jump;
if(setjmp(jump) != 0)
{
- fprintf(stderr, "\tin {{name}}\n");
+ fprintf(stderr, "\tin {{name}} on line %zu\n", line);
Stack_rewind(stack, stackSnapshot);
Environment_setLive(environment, false);
struct Closure
{
Environment* closed;
- Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, jmp_buf);
+ Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, const unsigned long, jmp_buf);
};
struct List;
return result;
}
-// TODO Make this conditionally added
-Object operator$negate(Object input)
+{% if 'pow' in builtins %}
+Object builtin$pow$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
{
- assert(input.type == INTEGER);
+ // Must unload items in reverse order
+ Object exponent = Stack_pop(stack);
+ Object base = Stack_pop(stack);
+
+ assert(base.type == INTEGER);
+ assert(exponent.type == INTEGER);
Object result;
result.type = INTEGER;
- result.instance.integer = -input.instance.integer;
+ result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
return result;
}
-// TODO Make this conditionally added
-Object operator$concatenate(Stack* stack, jmp_buf parentJump, size_t line)
+Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } };
+{% endif %}
+
+Object builtin$negate$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 1);
+
+ Object argument = Stack_pop(stack);
+
+ assert(argument.type == INTEGER);
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (-argument.instance.integer)
+ };
+
+ return result;
+}
+Object builtin$negate = { CLOSURE, (Instance)(Closure){ NULL, builtin$negate$implementation } };
+
+{% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %}
+Object builtin${{ op }}$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
+
+ {% if op == 'lt' %}
+ if(left.instance.integer < right.instance.integer)
+ {% elif op == 'gt' %}
+ if(left.instance.integer > right.instance.integer)
+ {% elif op == 'lte' %}
+ if(left.instance.integer <= right.instance.integer)
+ {% elif op == 'gte' %}
+ if(left.instance.integer >= right.instance.integer)
+ {% elif op == 'eq' %}
+ if(left.instance.integer == right.instance.integer)
+ {% elif op == 'neq' %}
+ if(left.instance.integer != right.instance.integer)
+ {% endif %}
+ {
+ return builtin$true;
+ }
+ else
+ {
+ return builtin$false;
+ }
+}
+Object builtin${{ op }} = { CLOSURE, (Instance)(Closure){ NULL, builtin${{ op }}$implementation } };
+{% endfor %}
+
+Object builtin$concat$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
{
+ assert(argc == 2);
+
Object right = Stack_pop(stack);
Object left = Stack_pop(stack);
Object result = { STRING_CONCATENATION, (Instance)concatenation };
return result;
}
+Object builtin$concat = { CLOSURE, (Instance)(Closure){ NULL, builtin$concat$implementation } };
-{% for id in infix_declarations %}
-Object operator${{ id.name }}(Stack* stack, jmp_buf parentJump, size_t line)
+Object builtin$add$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer + right.instance.integer)
+ };
+
+ return result;
+}
+Object builtin$add = { CLOSURE, (Instance)(Closure){ NULL, builtin$add$implementation } };
+
+Object builtin$subtract$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer - right.instance.integer)
+ };
+
+ return result;
+}
+Object builtin$subtract = { CLOSURE, (Instance)(Closure){ NULL, builtin$subtract$implementation } };
+
+Object builtin$multiply$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
Object right = Stack_pop(stack);
Object left = Stack_pop(stack);
- assert(left.type == {{ id.in_type.upper() }});
- assert(right.type == {{ id.in_type.upper() }});
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer * right.instance.integer)
+ };
+
+ return result;
+}
+Object builtin$multiply = { CLOSURE, (Instance)(Closure){ NULL, builtin$multiply$implementation } };
+
+Object builtin$integer_divide$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
- {% if id.name == 'integerDivide' or id.name == 'modularDivide' %}
if(right.instance.integer == 0)
{
fprintf(stderr, "DivisionByZeroError on line %zu\n", line);
longjmp(parentJump, 1);
}
- {% endif %}
- Object result;
- result.type = {{ id.out_type.upper() }};
- result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }};
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer / right.instance.integer)
+ };
+
return result;
}
-{% endfor %}
+Object builtin$integer_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$integer_divide$implementation } };
-{% if 'pow' in builtins %}
-Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parentJump)
+Object builtin$modular_divide$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
{
- // Must unload items in reverse order
- Object exponent = Stack_pop(stack);
- Object base = Stack_pop(stack);
+ assert(argc == 2);
- assert(base.type == INTEGER);
- assert(exponent.type == INTEGER);
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == INTEGER);
+ assert(right.type == INTEGER);
+
+ if(right.instance.integer == 0)
+ {
+ fprintf(stderr, "DivisionByZeroError on line %zu\n", line);
+ longjmp(parentJump, 1);
+ }
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer % right.instance.integer)
+ };
- Object result;
- result.type = INTEGER;
- result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
return result;
}
+Object builtin$modular_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$modular_divide$implementation } };
-Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } };
-{% endif %}
+Object builtin$field$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ assert(left.type == STRUCTURE);
+ assert(right.type == STRING_LITERAL);
+
+ Object result = (Object){
+ INTEGER,
+ (Instance)(int32_t) (left.instance.integer % right.instance.integer)
+ };
+
+ return result;
+}
+Object builtin$field = { CLOSURE, (Instance)(Closure){ NULL, builtin$field$implementation } };
+
+Object builtin$get$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
+{
+ assert(argc == 2);
+
+ Object right = Stack_pop(stack);
+ Object left = Stack_pop(stack);
+
+ return List_get(&left, right);
+}
+Object builtin$get = { CLOSURE, (Instance)(Closure){ NULL, builtin$get$implementation } };
{% if 'print' in builtins %}
-Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parentJump)
+Object builtin$print$implementation(
+ EnvironmentPool* environmentPool,
+ Environment* parent,
+ size_t argc,
+ Stack* stack,
+ const unsigned long line,
+ jmp_buf parentJump)
{
Stack reverse_stack;
Stack_initialize(&reverse_stack);
case STRING_CONCATENATION:
Stack_push(stack, output.instance.string_concatenation->left);
- builtin$print$implementation(NULL, NULL, 1, stack, parentJump);
+ builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump);
Stack_push(stack, output.instance.string_concatenation->right);
- builtin$print$implementation(NULL, NULL, 1, stack, parentJump);
+ builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump);
break;
case STRING_LITERAL:
Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
{% endfor %}
+ Environment_set(environment, "true", builtin$true);
+ Environment_set(environment, "false", builtin$false);
+ Environment_set(environment, "__add__", builtin$add);
+ Environment_set(environment, "__subtract__", builtin$subtract);
+ Environment_set(environment, "__multiply__", builtin$multiply);
+ Environment_set(environment, "__integer_divide__", builtin$integer_divide);
+ Environment_set(environment, "__modular_divide__", builtin$modular_divide);
+ Environment_set(environment, "__negate__", builtin$negate);
+ Environment_set(environment, "__concat__", builtin$concat);
+ Environment_set(environment, "__field__", builtin$field);
+ Environment_set(environment, "__get__", builtin$get);
+
+ {% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %}
+ Environment_set(environment, "__{{ op }}__", builtin${{ op }});
+ {% endfor %}
+
{% for statement in statements %}
{{ statement }}
{% endfor %}
Token = collections.namedtuple(
'Token',
- [
+ (
'type',
'match',
+ 'metadata',
+ ),
+)
+
+NodeMetadata = collections.namedtuple(
+ 'NodeMetadata',
+ (
'index',
'line',
- ],
+ ),
)
def _make_token_matcher(definition):
return (
True,
index + len(match.group()),
- Token(type=name, match=match.group(), index=index, line=line),
+ Token(
+ type=name,
+ match=match.group(),
+ metadata=NodeMetadata(
+ index=index,
+ line=line,
+ ),
+ ),
)
return token_matcher
],
)
-CDotExpression = collections.namedtuple(
- 'CDotExpression',
- [
- 'instance',
- 'symbol',
- 'symbol_list_index',
- ],
-)
-
-CNegationExpression = collections.namedtuple(
- 'CNegationExpression',
- [
- 'value',
- ],
-)
-
-CFunctionCallForFurInfixOperator = collections.namedtuple(
- 'CFunctionCallForFurInfixOperator',
- [
- 'metadata',
- 'name',
- ],
-)
-
CPushStatement = collections.namedtuple(
'CPushStatement',
(
CFunctionCallExpression = collections.namedtuple(
'CFunctionCallExpression',
- [
+ (
+ 'metadata',
'function_expression',
'argument_count',
- ],
+ ),
)
# TODO We are currently not changing variables, just preventing them from being accessed.
symbol_list_index=symbol_list_index,
)
-CInfixDeclaration = collections.namedtuple(
- 'CInfixDeclaration',
- [
- 'name',
- 'in_type',
- 'out_type',
- 'operator',
- ],
-)
-
-FUR_INFIX_OPERATOR_TO_C_FUNCTION = {
- '++': 'concatenate',
-}
-
-FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR = {
- '+': CInfixDeclaration(name='add', in_type='integer', out_type='integer', operator='+'),
- '-': CInfixDeclaration(name='subtract', in_type='integer', out_type='integer', operator='-'),
- '*': CInfixDeclaration(name='multiply', in_type='integer', out_type='integer', operator='*'),
- '//': CInfixDeclaration(name='integerDivide', in_type='integer', out_type='integer', operator='/'),
- '%': CInfixDeclaration(name='modularDivide', in_type='integer', out_type='integer', operator='%'),
- 'and': CInfixDeclaration(name='and', in_type='boolean', out_type='boolean', operator='&&'),
- 'or': CInfixDeclaration(name='or', in_type='boolean', out_type='boolean', operator='||'),
- '==': CInfixDeclaration(name='equals', in_type='integer', out_type='boolean', operator='=='),
- '!=': CInfixDeclaration(name='notEquals', in_type='integer', out_type='boolean', operator='!='),
- '<=': CInfixDeclaration(name='lessThanOrEqual', in_type='integer', out_type='boolean', operator='<='),
- '>=': CInfixDeclaration(name='greaterThanOrEqual', in_type='integer', out_type='boolean', operator='>='),
- '<': CInfixDeclaration(name='lessThan', in_type='integer', out_type='boolean', operator='<'),
- '>': CInfixDeclaration(name='greaterThan', in_type='integer', out_type='boolean', operator='>'),
-}
-
-def transform_infix_operator_without_c_equivalent(accumulators, expression):
- return CFunctionCallForFurInfixOperator(
- metadata=expression.metadata,
- name='concatenate',
- )
-
-def transform_infix_expression(accumulators, expression):
- if expression.operator in FUR_INFIX_OPERATOR_TO_C_FUNCTION:
- return transform_infix_operator_without_c_equivalent(accumulators, expression)
-
- accumulators.operator_set.add(FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator])
-
- return CFunctionCallForFurInfixOperator(
- metadata=expression.metadata,
- name=FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator].name,
- )
-
def transform_integer_literal_expression(accumulators, expression):
return CIntegerLiteral(value=expression.integer)
-def transform_negation_expression(accumulators, expression):
- return CNegationExpression(
- value=transform_expression(accumulators, expression.internal_expression),
- )
-
CListConstructExpression = collections.namedtuple(
'CListConstructExpression',
[
value_list_variable=expression.value_list_variable,
)
-def transform_dot_expression(accumulators, expression):
- try:
- symbol_list_index = accumulators.symbol_list.index(expression.field)
-
- except ValueError:
- symbol_list_index = len(accumulators.symbol_list)
- accumulators.symbol_list.append(expression.field)
-
- return CDotExpression(
- instance=transform_variable_expression(accumulators, expression.instance),
- symbol=expression.field,
- symbol_list_index=symbol_list_index,
- )
-
def transform_list_construct_expression(accumulators, expression):
return CListConstructExpression(allocate=expression.allocate)
)
def transform_expression(accumulators, expression):
- # TODO Clean up handlers for parsing expressions
return {
- parsing.FurInfixExpression: transform_infix_expression,
- parsing.FurIntegerLiteralExpression: transform_integer_literal_expression,
- parsing.FurNegationExpression: transform_negation_expression,
- parsing.FurStringLiteralExpression: transform_string_literal_expression,
- normalization.NormalDotExpression: transform_dot_expression,
normalization.NormalFunctionCallExpression: transform_function_call_expression,
- normalization.NormalInfixExpression: transform_infix_expression,
normalization.NormalIntegerLiteralExpression: transform_integer_literal_expression,
normalization.NormalListConstructExpression: transform_list_construct_expression,
normalization.NormalListGetExpression: transform_list_get_expression,
- normalization.NormalNegationExpression: transform_negation_expression,
normalization.NormalStructureLiteralExpression: transform_structure_literal_expression,
normalization.NormalStringLiteralExpression: transform_string_literal_expression,
normalization.NormalSymbolExpression: transform_symbol_expression,
def transform_function_call_expression(accumulators, function_call):
# TODO Use the symbol from SYMBOL LIST
return CFunctionCallExpression(
+ metadata=function_call.metadata,
function_expression=transform_expression(accumulators, function_call.function_expression),
argument_count=function_call.argument_count,
)
def transform_statement(accumulators, statement):
return {
- parsing.FurExpressionStatement: transform_expression_statement,
normalization.NormalArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
normalization.NormalAssignmentStatement: transform_symbol_assignment_statement,
normalization.NormalExpressionStatement: transform_expression_statement,