aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compile.c22
-rw-r--r--src/parse.c10
-rw-r--r--src/stdlib/tables.c10
-rw-r--r--src/tomo.c2
-rw-r--r--src/typecheck.c13
5 files changed, 40 insertions, 17 deletions
diff --git a/src/compile.c b/src/compile.c
index a4f5b3ec..46a0e607 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -1468,7 +1468,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
// If we're iterating over a comprehension, that's actually just doing
// one loop, we don't need to compile the comprehension as an array
// comprehension. This is a common case for reducers like `(+: i*2 for i in 5)`
- // or `(and) x:is_good() for x in xs`
+ // or `(and) x.is_good() for x in xs`
if (for_->iter->tag == Comprehension) {
auto comp = Match(for_->iter, Comprehension);
ast_t *body = for_->body;
@@ -1552,7 +1552,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
stop);
} else if (for_->iter->tag == MethodCall && streq(Match(for_->iter, MethodCall)->name, "onward") &&
get_type(env, Match(for_->iter, MethodCall)->self)->tag == BigIntType) {
- // Special case for Int:onward()
+ // Special case for Int.onward()
arg_ast_t *args = Match(for_->iter, MethodCall)->args;
arg_t *arg_spec = new(arg_t, .name="step", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"), .next=NULL);
CORD step = compile_arguments(env, for_->iter, arg_spec, args);
@@ -1933,7 +1933,7 @@ CORD compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bool
++depth;
// Passing a literal value won't trigger an incref, because it's ephemeral,
- // e.g. [10, 20]:reversed()
+ // e.g. [10, 20].reversed()
if (t->tag != PointerType && needs_incref && !can_be_mutated(env, ast))
needs_incref = false;
@@ -2001,7 +2001,7 @@ CORD compile_to_type(env_t *env, ast_t *ast, type_t *t)
// should be from what we know the specific type of the return value is,
// but it requires a bit of special logic.
// For example:
- // x : [Int?] = [none]:sorted()
+ // x : [Int?] = [none].sorted()
// Here, we know that `[none]` is `[Int?]`, but we need to thread that
// information through the compiler using an `ExplicitlyTyped` node.
if (ast->tag == MethodCall) {
@@ -2924,7 +2924,7 @@ CORD compile(env_t *env, ast_t *ast)
if (streq(call->name, "serialized")) {
if (call->args)
- code_err(ast, ":serialized() doesn't take any arguments");
+ code_err(ast, ".serialized() doesn't take any arguments");
return CORD_all("generic_serialize((", compile_declaration(self_t, "[1]"), "){",
compile(env, call->self), "}, ", compile_type_info(self_t), ")");
}
@@ -2934,6 +2934,18 @@ CORD compile(env_t *env, ast_t *ast)
for (; self_value_t->tag == PointerType; self_value_t = Match(self_value_t, PointerType)->pointed)
pointer_depth += 1;
+ if (self_value_t->tag == TypeInfoType || self_value_t->tag == ModuleType) {
+ return compile(env, WrapAST(ast, FunctionCall, .fn=WrapAST(call->self, FieldAccess, .fielded=call->self, .field=call->name),
+ .args=call->args));
+ }
+
+ type_t *field_type = get_field_type(self_value_t, call->name);
+ if (field_type && field_type->tag == ClosureType)
+ field_type = Match(field_type, ClosureType)->fn;
+ if (field_type && field_type->tag == FunctionType)
+ return compile(env, WrapAST(ast, FunctionCall, .fn=WrapAST(call->self, FieldAccess, .fielded=call->self, .field=call->name),
+ .args=call->args));
+
CORD self = compile(env, call->self);
#define EXPECT_POINTER(article, name) do { \
diff --git a/src/parse.c b/src/parse.c
index fa021e28..d686bb6d 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -847,8 +847,8 @@ PARSER(parse_reduction) {
ast_t *new_term;
progress = (false
|| (new_term=parse_index_suffix(ctx, key))
- || (new_term=parse_field_suffix(ctx, key))
|| (new_term=parse_method_call_suffix(ctx, key))
+ || (new_term=parse_field_suffix(ctx, key))
|| (new_term=parse_fncall_suffix(ctx, key))
|| (new_term=parse_optional_suffix(ctx, key))
|| (new_term=parse_non_optional_suffix(ctx, key))
@@ -1095,6 +1095,7 @@ PARSER(parse_heap_alloc) {
ast_t *new_term;
if ((new_term=parse_index_suffix(ctx, val))
|| (new_term=parse_fncall_suffix(ctx, val))
+ || (new_term=parse_method_call_suffix(ctx, val))
|| (new_term=parse_field_suffix(ctx, val))) {
val = new_term;
} else break;
@@ -1121,6 +1122,7 @@ PARSER(parse_stack_reference) {
ast_t *new_term;
if ((new_term=parse_index_suffix(ctx, val))
|| (new_term=parse_fncall_suffix(ctx, val))
+ || (new_term=parse_method_call_suffix(ctx, val))
|| (new_term=parse_field_suffix(ctx, val))) {
val = new_term;
} else break;
@@ -1462,8 +1464,8 @@ PARSER(parse_term) {
ast_t *new_term;
progress = (false
|| (new_term=parse_index_suffix(ctx, term))
- || (new_term=parse_field_suffix(ctx, term))
|| (new_term=parse_method_call_suffix(ctx, term))
+ || (new_term=parse_field_suffix(ctx, term))
|| (new_term=parse_fncall_suffix(ctx, term))
|| (new_term=parse_optional_suffix(ctx, term))
|| (new_term=parse_non_optional_suffix(ctx, term))
@@ -1479,7 +1481,7 @@ ast_t *parse_method_call_suffix(parse_ctx_t *ctx, ast_t *self) {
const char *start = self->start;
const char *pos = self->end;
- if (!match(&pos, ":")) return NULL;
+ if (!match(&pos, ".")) return NULL;
if (*pos == ' ') return NULL;
const char *fn = get_id(&pos);
if (!fn) return NULL;
@@ -1622,8 +1624,8 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn
ast_t *new_term;
progress = (false
|| (new_term=parse_index_suffix(ctx, key))
- || (new_term=parse_field_suffix(ctx, key))
|| (new_term=parse_method_call_suffix(ctx, key))
+ || (new_term=parse_field_suffix(ctx, key))
|| (new_term=parse_fncall_suffix(ctx, key))
|| (new_term=parse_optional_suffix(ctx, key))
|| (new_term=parse_non_optional_suffix(ctx, key))
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index dfa35236..58c1b2e4 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -446,10 +446,10 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
// Table comparison rules:
// - If two tables have different keys, then compare as if comparing a
// sorted array of the keys of the two tables:
- // `x.keys:sorted() <> y.keys:sorted()`
+ // `x.keys.sorted() <> y.keys.sorted()`
// - Otherwise, compare as if comparing arrays of values for the sorted key
// arrays:
- // `[x[k] for k in x.keys:sorted()] <> [y[k] for k in y.keys:sorted()]`
+ // `[x[k] for k in x.keys.sorted()] <> [y[k] for k in y.keys.sorted()]`
//
// We can do this in _linear_ time if we find the smallest `k` such that
// `x[k] != y[k]`, as well as the largest key in `x` and `y`.
@@ -637,7 +637,7 @@ public Table_t Table$from_entries(Array_t entries, const TypeInfo_t *type)
// Overlap is "set intersection" in formal terms
public Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type)
{
- // Return a table such that t[k]==a[k] for all k such that a:has(k), b:has(k), and a[k]==b[k]
+ // Return a table such that t[k]==a[k] for all k such that a.has(k), b.has(k), and a[k]==b[k]
Table_t result = {};
const size_t offset = value_offset(type);
for (int64_t i = 0; i < Table$length(a); i++) {
@@ -659,7 +659,7 @@ public Table_t Table$overlap(Table_t a, Table_t b, const TypeInfo_t *type)
// With is "set union" in formal terms
public Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type)
{
- // return a table such that t[k]==b[k] for all k such that b:has(k), and t[k]==a[k] for all k such that a:has(k) and not b:has(k)
+ // return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and not b.has(k)
Table_t result = {};
const size_t offset = value_offset(type);
for (int64_t i = 0; i < Table$length(a); i++) {
@@ -684,7 +684,7 @@ public Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type)
// Without is "set difference" in formal terms
public Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type)
{
- // Return a table such that t[k]==a[k] for all k such that not b:has(k) or b[k] != a[k]
+ // Return a table such that t[k]==a[k] for all k such that not b.has(k) or b[k] != a[k]
Table_t result = {};
const size_t offset = value_offset(type);
for (int64_t i = 0; i < Table$length(a); i++) {
diff --git a/src/tomo.c b/src/tomo.c
index 13a855c6..7eb53f76 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -241,8 +241,6 @@ int main(int argc, char *argv[])
if (files.length < 1)
print_err("No file specified!");
- else if (files.length != 1)
- print_err("Too many files specified!");
quiet = !verbose;
diff --git a/src/typecheck.c b/src/typecheck.c
index c5243195..21e02460 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -550,7 +550,7 @@ type_t *get_method_type(env_t *env, ast_t *self, const char *name)
{
binding_t *b = get_namespace_binding(env, self, name);
if (!b || !b->type)
- code_err(self, "No such method: ", type_to_str(get_type(env, self)), ":", name, "(...)");
+ code_err(self, "No such method: ", type_to_str(get_type(env, self)), ".", name, "(...)");
return b->type;
}
@@ -895,6 +895,12 @@ type_t *get_type(env_t *env, ast_t *ast)
type_t *self_value_t = get_type(env, call->self);
if (!self_value_t) code_err(call->self, "Couldn't get the type of this value");
self_value_t = value_type(self_value_t);
+
+ if (self_value_t->tag == TypeInfoType || self_value_t->tag == ModuleType) {
+ return get_type(env, WrapAST(ast, FunctionCall, .fn=WrapAST(call->self, FieldAccess, .fielded=call->self, .field=call->name),
+ .args=call->args));
+ }
+
switch (self_value_t->tag) {
case ArrayType: {
type_t *item_type = Match(self_value_t, ArrayType)->item_type;
@@ -952,6 +958,11 @@ type_t *get_type(env_t *env, ast_t *ast)
code_err(ast, "There is no '", call->name, "' method for ", type_to_str(self_value_t), " tables");
}
default: {
+ type_t *field_type = get_field_type(self_value_t, call->name);
+ if (field_type && field_type->tag == ClosureType)
+ field_type = Match(field_type, ClosureType)->fn;
+ if (field_type && field_type->tag == FunctionType)
+ return Match(field_type, FunctionType)->ret;
type_t *fn_type_t = get_method_type(env, call->self, call->name);
if (!fn_type_t)
code_err(ast, "No such method!");