aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c48
-rw-r--r--src/compile/comparisons.c14
-rw-r--r--src/compile/reductions.c7
-rw-r--r--src/formatter/formatter.c50
-rw-r--r--src/formatter/utils.c38
-rw-r--r--src/formatter/utils.h1
-rw-r--r--src/parse/expressions.c4
7 files changed, 92 insertions, 70 deletions
diff --git a/src/ast.c b/src/ast.c
index 3b58b919..03843438 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -76,32 +76,40 @@ CONSTFUNC const char *binop_method_name(ast_e tag) {
CONSTFUNC const char *binop_operator(ast_e tag) {
switch (tag) {
- case Multiply:
- case MultiplyUpdate: return "*";
- case Divide:
- case DivideUpdate: return "/";
- case Mod:
- case ModUpdate: return "%";
- case Plus:
- case PlusUpdate: return "+";
- case Minus:
- case MinusUpdate: return "-";
- case LeftShift:
- case LeftShiftUpdate: return "<<";
- case RightShift:
- case RightShiftUpdate: return ">>";
- case And:
- case AndUpdate: return "&";
- case Or:
- case OrUpdate: return "|";
- case Xor:
- case XorUpdate: return "^";
+ case Power: return "^";
+ case PowerUpdate: return "^=";
+ case Concat: return "++";
+ case ConcatUpdate: return "++=";
+ case Multiply: return "*";
+ case MultiplyUpdate: return "*=";
+ case Divide: return "/";
+ case DivideUpdate: return "/=";
+ case Mod: return "mod";
+ case ModUpdate: return "mod=";
+ case Mod1: return "mod1";
+ case Mod1Update: return "mod1=";
+ case Plus: return "+";
+ case PlusUpdate: return "+=";
+ case Minus: return "-";
+ case MinusUpdate: return "-=";
+ case LeftShift: return "<<";
+ case LeftShiftUpdate: return "<<=";
+ case RightShift: return ">>";
+ case RightShiftUpdate: return ">>=";
+ case And: return "and";
+ case AndUpdate: return "and=";
+ case Or: return "or";
+ case OrUpdate: return "or=";
+ case Xor: return "xor";
+ case XorUpdate: return "xor=";
case Equals: return "==";
case NotEquals: return "!=";
case LessThan: return "<";
case LessThanOrEquals: return "<=";
case GreaterThan: return ">";
case GreaterThanOrEquals: return ">=";
+ case Min: return "_min_";
+ case Max: return "_max_";
default: return NULL;
}
}
diff --git a/src/compile/comparisons.c b/src/compile/comparisons.c
index d73664de..d7531261 100644
--- a/src/compile/comparisons.c
+++ b/src/compile/comparisons.c
@@ -7,6 +7,18 @@
#include "../typecheck.h"
#include "compilation.h"
+static CONSTFUNC const char *comparison_operator(ast_e tag) {
+ switch (tag) {
+ case Equals: return "==";
+ case NotEquals: return "!=";
+ case LessThan: return "<";
+ case LessThanOrEquals: return "<=";
+ case GreaterThan: return ">";
+ case GreaterThanOrEquals: return ">=";
+ default: return NULL;
+ }
+}
+
Text_t compile_comparison(env_t *env, ast_t *ast) {
switch (ast->tag) {
@@ -75,7 +87,7 @@ Text_t compile_comparison(env_t *env, ast_t *ast) {
if (ast->tag == Compare)
return Texts("generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ")");
- const char *op = binop_operator(ast->tag);
+ const char *op = comparison_operator(ast->tag);
switch (operand_t->tag) {
case BigIntType: return Texts("(Int$compare_value(", lhs, ", ", rhs, ") ", op, " 0)");
case BoolType:
diff --git a/src/compile/reductions.c b/src/compile/reductions.c
index e0477a9c..1652384c 100644
--- a/src/compile/reductions.c
+++ b/src/compile/reductions.c
@@ -12,6 +12,7 @@ public
Text_t compile_reduction(env_t *env, ast_t *ast) {
DeclareMatch(reduction, ast, Reduction);
ast_e op = reduction->op;
+ const char *op_str = binop_operator(op);
type_t *iter_t = get_type(env, reduction->iter);
type_t *item_t = get_iterated_type(iter_t);
@@ -29,7 +30,7 @@ Text_t compile_reduction(env_t *env, ast_t *ast) {
type_t *item_value_type = item_t;
ast_t *item_value = item;
if (reduction->key) {
- set_binding(body_scope, "$", item_t, compile(body_scope, item));
+ set_binding(body_scope, op_str, item_t, compile(body_scope, item));
item_value = reduction->key;
item_value_type = get_type(body_scope, reduction->key);
}
@@ -67,7 +68,7 @@ Text_t compile_reduction(env_t *env, ast_t *ast) {
ast_e cmp_op = op == Min ? LessThan : GreaterThan;
if (reduction->key) {
env_t *key_scope = fresh_scope(env);
- set_binding(key_scope, "$", item_t, item_code);
+ set_binding(key_scope, op_str, item_t, item_code);
type_t *key_type = get_type(key_scope, reduction->key);
Text_t superlative_key = op == Min ? Text("min_key") : Text("max_key");
code = Texts(code, compile_declaration(key_type, superlative_key), ";\n");
@@ -111,7 +112,7 @@ Text_t compile_reduction(env_t *env, ast_t *ast) {
type_t *reduction_type = Match(get_type(env, ast), OptionalType)->type;
ast_t *item_value = item;
if (reduction->key) {
- set_binding(body_scope, "$", item_t, compile(body_scope, item));
+ set_binding(body_scope, op_str, item_t, compile(body_scope, item));
item_value = reduction->key;
}
diff --git a/src/formatter/formatter.c b/src/formatter/formatter.c
index a48a1f33..5dd65d04 100644
--- a/src/formatter/formatter.c
+++ b/src/formatter/formatter.c
@@ -44,6 +44,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
/*inline*/ case LangDef:
/*inline*/ case Extend:
/*inline*/ case FunctionDef:
+ /*inline*/ case ConvertDef:
/*inline*/ case DocTest:
return NONE_TEXT;
/*inline*/ case Lambda: {
@@ -232,6 +233,14 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
ast_t *key = ast->tag == Min ? Match(ast, Min)->key : Match(ast, Max)->key;
return Texts(lhs, key ? fmt_inline(key, comments) : (ast->tag == Min ? Text(" _min_ ") : Text(" _max_ ")), rhs);
}
+ /*inline*/ case Reduction: {
+ DeclareMatch(reduction, ast, Reduction);
+ if (reduction->key) {
+ return Texts("(", fmt_inline(reduction->key, comments), ": ", fmt_inline(reduction->iter, comments));
+ } else {
+ return Texts("(", binop_operator(reduction->op), ": ", fmt_inline(reduction->iter, comments));
+ }
+ }
/*inline*/ case None:
return Text("none");
/*inline*/ case Bool:
@@ -259,7 +268,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
}
/*inline*/ case BINOP_CASES: {
binary_operands_t operands = BINARY_OPERANDS(ast);
- const char *op = binop_tomo_operator(ast->tag);
+ const char *op = binop_operator(ast->tag);
Text_t lhs = fmt_inline(operands.lhs, comments);
Text_t rhs = fmt_inline(operands.rhs, comments);
@@ -274,7 +283,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) {
rhs = parenthesize(rhs, EMPTY_TEXT);
Text_t space = op_tightness[ast->tag] >= op_tightness[Multiply] ? EMPTY_TEXT : Text(" ");
- return Texts(lhs, space, Text$from_str(binop_tomo_operator(ast->tag)), space, rhs);
+ return Texts(lhs, space, Text$from_str(binop_operator(ast->tag)), space, rhs);
}
default: {
fail("Formatting not implemented for: ", ast_to_sexp(ast));
@@ -412,6 +421,16 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
code = Texts(code, ")\n", indent, single_indent, fmt(lambda->body, comments, Texts(indent, single_indent)));
return Texts(code);
}
+ /*multiline*/ case ConvertDef: {
+ DeclareMatch(convert, ast, ConvertDef);
+ Text_t code = Texts("convert (", format_args(convert->args, comments, indent));
+ if (convert->ret_type)
+ code = Texts(code, convert->args ? Text(" -> ") : Text("-> "), format_type(convert->ret_type));
+ if (convert->cache) code = Texts(code, "; cache=", fmt(convert->cache, comments, indent));
+ if (convert->is_inline) code = Texts(code, "; inline");
+ code = Texts(code, ")\n", indent, single_indent, fmt(convert->body, comments, Texts(indent, single_indent)));
+ return Texts(code);
+ }
/*multiline*/ case StructDef: {
DeclareMatch(def, ast, StructDef);
Text_t code = Texts("struct ", Text$from_str(def->name), "(", format_args(def->fields, comments, indent));
@@ -484,6 +503,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
return Texts(fmt(entry->key, comments, indent), "=", fmt(entry->value, comments, indent));
}
/*multiline*/ case Declare: {
+ if (inlined_fits) return inlined;
DeclareMatch(decl, ast, Declare);
Text_t code = fmt(decl->var, comments, indent);
if (decl->type) code = Texts(code, " : ", format_type(decl->type));
@@ -492,6 +512,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
return code;
}
/*multiline*/ case Assign: {
+ if (inlined_fits) return inlined;
DeclareMatch(assign, ast, Assign);
Text_t code = EMPTY_TEXT;
for (ast_list_t *target = assign->targets; target; target = target->next) {
@@ -508,15 +529,18 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
/*multiline*/ case Pass:
return Text("pass");
/*multiline*/ case Return: {
+ if (inlined_fits) return inlined;
ast_t *value = Match(ast, Return)->value;
return value ? Texts("return ", fmt(value, comments, indent)) : Text("return");
}
/*inline*/ case Not: {
+ if (inlined_fits) return inlined;
ast_t *val = Match(ast, Not)->value;
if (is_binary_operation(val)) return Texts("not ", termify(val, comments, indent));
else return Texts("not ", fmt(val, comments, indent));
}
/*inline*/ case Negative: {
+ if (inlined_fits) return inlined;
ast_t *val = Match(ast, Negative)->value;
if (is_binary_operation(val)) return Texts("-", termify(val, comments, indent));
else return Texts("-", fmt(val, comments, indent));
@@ -542,10 +566,12 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
return Texts(termify(val, comments, indent), "!");
}
/*multiline*/ case FieldAccess: {
+ if (inlined_fits) return inlined;
DeclareMatch(access, ast, FieldAccess);
return Texts(termify(access->fielded, comments, indent), ".", Text$from_str(access->field));
}
/*multiline*/ case Index: {
+ if (inlined_fits) return inlined;
DeclareMatch(index, ast, Index);
if (index->index)
return Texts(termify(index->indexed, comments, indent), "[", fmt(index->index, comments, indent), "]");
@@ -583,14 +609,26 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
assert(inlined.length > 0);
return inlined;
}
- /*inline*/ case Min:
- /*inline*/ case Max: {
+ /*multiline*/ case Min:
+ /*multiline*/ case Max: {
+ if (inlined_fits) return inlined;
Text_t lhs = termify(ast->tag == Min ? Match(ast, Min)->lhs : Match(ast, Max)->lhs, comments, indent);
Text_t rhs = termify(ast->tag == Min ? Match(ast, Min)->rhs : Match(ast, Max)->rhs, comments, indent);
ast_t *key = ast->tag == Min ? Match(ast, Min)->key : Match(ast, Max)->key;
Text_t op = key ? fmt(key, comments, indent) : (ast->tag == Min ? Text("_min_") : Text("_max_"));
return Texts(lhs, " ", op, " ", rhs);
}
+ /*multiline*/ case Reduction: {
+ if (inlined_fits) return inlined;
+ DeclareMatch(reduction, ast, Reduction);
+ if (reduction->key) {
+ return Texts("(", fmt(reduction->key, comments, Texts(indent, single_indent)), ": ",
+ fmt(reduction->iter, comments, Texts(indent, single_indent)));
+ } else {
+ return Texts("(", binop_operator(reduction->op), ": ",
+ fmt(reduction->iter, comments, Texts(indent, single_indent)));
+ }
+ }
/*multiline*/ case Stop:
/*multiline*/ case Skip:
/*multiline*/ case None:
@@ -627,7 +665,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
/*multiline*/ case BINOP_CASES: {
if (inlined_fits) return inlined;
binary_operands_t operands = BINARY_OPERANDS(ast);
- const char *op = binop_tomo_operator(ast->tag);
+ const char *op = binop_operator(ast->tag);
Text_t lhs = fmt(operands.lhs, comments, indent);
Text_t rhs = fmt(operands.rhs, comments, indent);
@@ -641,7 +679,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
rhs = parenthesize(rhs, indent);
Text_t space = op_tightness[ast->tag] >= op_tightness[Multiply] ? EMPTY_TEXT : Text(" ");
- return Texts(lhs, space, Text$from_str(binop_tomo_operator(ast->tag)), space, rhs);
+ return Texts(lhs, space, Text$from_str(binop_operator(ast->tag)), space, rhs);
}
default: {
if (inlined_fits) return inlined;
diff --git a/src/formatter/utils.c b/src/formatter/utils.c
index a032ec2f..fa4ec806 100644
--- a/src/formatter/utils.c
+++ b/src/formatter/utils.c
@@ -74,44 +74,6 @@ CONSTFUNC ast_t *unwrap_block(ast_t *ast) {
return ast;
}
-CONSTFUNC const char *binop_tomo_operator(ast_e tag) {
- switch (tag) {
- case Power: return "^";
- case PowerUpdate: return "^=";
- case Concat: return "++";
- case ConcatUpdate: return "++=";
- case Multiply: return "*";
- case MultiplyUpdate: return "*=";
- case Divide: return "/";
- case DivideUpdate: return "/=";
- case Mod: return "mod";
- case ModUpdate: return "mod=";
- case Mod1: return "mod1";
- case Mod1Update: return "mod1=";
- case Plus: return "+";
- case PlusUpdate: return "+=";
- case Minus: return "-";
- case MinusUpdate: return "-=";
- case LeftShift: return "<<";
- case LeftShiftUpdate: return "<<=";
- case RightShift: return ">>";
- case RightShiftUpdate: return ">>=";
- case And: return "and";
- case AndUpdate: return "and=";
- case Or: return "or";
- case OrUpdate: return "or=";
- case Xor: return "xor";
- case XorUpdate: return "xor=";
- case Equals: return "==";
- case NotEquals: return "!=";
- case LessThan: return "<";
- case LessThanOrEquals: return "<=";
- case GreaterThan: return ">";
- case GreaterThanOrEquals: return ">=";
- default: return NULL;
- }
-}
-
OptionalText_t termify_inline(ast_t *ast, Table_t comments) {
if (range_has_comment(ast->start, ast->end, comments)) return NONE_TEXT;
switch (ast->tag) {
diff --git a/src/formatter/utils.h b/src/formatter/utils.h
index 9dc230e4..d847c2fb 100644
--- a/src/formatter/utils.h
+++ b/src/formatter/utils.h
@@ -26,6 +26,5 @@ CONSTFUNC bool should_have_blank_line(ast_t *ast);
Text_t indent_code(Text_t code);
Text_t parenthesize(Text_t code, Text_t indent);
CONSTFUNC ast_t *unwrap_block(ast_t *ast);
-CONSTFUNC const char *binop_tomo_operator(ast_e tag);
OptionalText_t termify_inline(ast_t *ast, Table_t comments);
Text_t termify(ast_t *ast, Table_t comments, Text_t indent);
diff --git a/src/parse/expressions.c b/src/parse/expressions.c
index 6104b2d2..32133fe9 100644
--- a/src/parse/expressions.c
+++ b/src/parse/expressions.c
@@ -49,7 +49,9 @@ ast_t *parse_reduction(parse_ctx_t *ctx, const char *pos) {
ast_e op = match_binary_operator(&pos);
if (op == Unknown) return NULL;
- ast_t *key = NewAST(ctx->file, pos, pos, Var, .name = "$");
+ const char *op_str = binop_operator(op);
+ assert(op_str);
+ ast_t *key = NewAST(ctx->file, pos, pos, Var, .name = op_str);
for (bool progress = true; progress;) {
ast_t *new_term;
progress =