Skip to content

Commit

Permalink
Work on generic functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
asoffer committed Oct 6, 2023
1 parent bcd36fd commit 727bd36
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 20 deletions.
1 change: 1 addition & 0 deletions ir/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ cc_library(
"//parser:parse_tree",
"//parser:parse_tree_node_kind_xmacro",
"//type",
"@asoffer_jasmin//jasmin:execute",
"@asoffer_jasmin//jasmin:value_stack",
"@asoffer_nth//nth/debug",
"@asoffer_nth//nth/debug/log",
Expand Down
15 changes: 11 additions & 4 deletions ir/builtin_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ nth::NoDestructor<IrFunction> Foreign([] {
return f;
}());

nth::NoDestructor<IrFunction> ForeignType([] {
IrFunction f(1, 1);
f.append<jasmin::Return>();
return f;
}());

Module BuiltinModule(GlobalFunctionRegistry& registry) {
uint32_t next_id = 0;

Expand All @@ -47,10 +53,11 @@ Module BuiltinModule(GlobalFunctionRegistry& registry) {
registry.Register(FunctionId(ModuleId::Builtin(), LocalFunctionId(next_id++)),
&*PrintFn);

m.Insert(resources.IdentifierIndex("foreign"),
{.qualified_type = type::QualifiedType(
type::Qualifier::Constant(), type::GenericFunction(nullptr)),
.value = {}});
m.Insert(
resources.IdentifierIndex("foreign"),
{.qualified_type = type::QualifiedType(
type::Qualifier::Constant(), type::GenericFunction(&*ForeignType)),
.value = {}});
registry.Register(FunctionId(ModuleId::Builtin(), LocalFunctionId(next_id++)),
&*Foreign);

Expand Down
14 changes: 7 additions & 7 deletions ir/emit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ void EmitContext::Push(jasmin::Value v, type::Type t) {
void EmitIr(nth::interval<ParseTree::Node::Index> node_range, EmitContext& context) {
ParseTree::Node::Index start = node_range.lower_bound();
for (auto const& [range, value_stack] : context.constants) {
if (range.lower_bound() < start) { continue; }
EmitNonConstant(nth::interval(start, range.lower_bound()), context);
// TODO: This type is wrong.
for (jasmin::Value const& v : value_stack) { context.Push(v, type::Bool); }
Expand All @@ -188,15 +189,14 @@ void EmitIr(nth::interval<ParseTree::Node::Index> node_range, EmitContext& conte
context.function_stack.back()->append<jasmin::Return>();
}

void Evaluate(nth::interval<ParseTree::Node::Index> subtree,
ParseTree const& tree,
DependentModules const& modules NTH_ATTRIBUTE(lifetimebound),
jasmin::ValueStack& value_stack) {
void EmitContext::Evaluate(nth::interval<ParseTree::Node::Index> subtree,
jasmin::ValueStack& value_stack) {
IrFunction f(0, 1);
EmitContext context(tree, modules, f);
EmitIr(subtree, context);
context.function_stack.back()->append<jasmin::Return>();
function_stack.push_back(&f);
EmitIr(subtree, *this);
f.append<jasmin::Return>();
jasmin::Execute(f, value_stack);
function_stack.pop_back();
}

} // namespace ic
8 changes: 3 additions & 5 deletions ir/emit.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct EmitContext {

void Push(jasmin::Value v, type::Type);

void Evaluate(nth::interval<ParseTree::Node::Index> subtree,
jasmin::ValueStack& value_stack);

ParseTree::Node const& Node(ParseTree::Node::Index index) {
return tree[index];
}
Expand Down Expand Up @@ -69,11 +72,6 @@ struct EmitContext {
void EmitIr(nth::interval<ParseTree::Node::Index> node_range,
EmitContext& context);

void Evaluate(nth::interval<ParseTree::Node::Index> subtree,
ParseTree const& tree,
DependentModules const& modules NTH_ATTRIBUTE(lifetimebound),
jasmin::ValueStack& value_stack);

} // namespace ic

#endif // ICARUS_IR_EMIT_H
17 changes: 17 additions & 0 deletions ir/ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "common/string.h"
#include "ir/module_id.h"
#include "jasmin/execute.h"
#include "nth/debug/debug.h"
#include "nth/debug/log/log.h"
#include "type/type.h"
Expand Down Expand Up @@ -199,6 +200,22 @@ void HandleParseTreeNodeCallExpression(ParseTree::Node::Index index,
} else {
NTH_UNIMPLEMENTED();
}
} else if (invocable_type.type().kind() ==
type::Type::Kind::GenericFunction) {
jasmin::ValueStack value_stack;
for (auto iter = context.ChildIndices(index).begin();
context.Node(*iter).kind !=
ParseTree::Node::Kind::InvocationArgumentStart;
++iter) {
context.emit.Evaluate(context.emit.tree.subtree_range(*iter),
value_stack);
}

jasmin::Execute(*static_cast<IrFunction const*>(
invocable_type.type().AsGenericFunction().data()),
value_stack);
context.type_stack.push_back(type::QualifiedType(
type::Qualifier::Constant(), value_stack.pop<type::Type>()));
} else {
NTH_UNIMPLEMENTED("{}") <<= {node};
}
Expand Down
11 changes: 7 additions & 4 deletions ir/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ struct IrContext {
return emit.tree[index];
}

auto ChildIndices(ParseTree::Node::Index index) {
return emit.tree.child_indices(index);
}
auto Children(ParseTree::Node::Index index) {
return emit.tree.children(index);
}
Expand All @@ -31,12 +34,12 @@ struct IrContext {
std::optional<T> EvaluateAs(ParseTree::Node::Index subtree_root_index) {
T result;
nth::interval range = emit.tree.subtree_range(subtree_root_index);
auto [iter, inserted] = emit.constants.try_emplace(range);
jasmin::ValueStack value_stack;
emit.Evaluate(range, value_stack);
auto [iter, inserted] = emit.constants.try_emplace(range, std::move(value_stack));
NTH_REQUIRE((v.harden), inserted);
jasmin::ValueStack& value_stack = iter->second;
Evaluate(range, emit.tree, emit.modules, value_stack);
if (IcarusDeserializeValue(
std::span(value_stack.begin(), value_stack.end()), result)) {
std::span(iter->second.begin(), iter->second.end()), result)) {
return result;
} else {
return std::nullopt;
Expand Down
4 changes: 4 additions & 0 deletions type/type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ std::vector<Type> const& FunctionType::returns() const {
return ic::type::returns->from_index(functions->from_index(data()).second);
}

void const* GenericFunctionType::data() const {
return generic_function_types->from_index(BasicType::data());
}

size_t JasminSize(Type t) {
switch (t.kind()) {
case Type::Kind::Primitive: return 1;
Expand Down
23 changes: 23 additions & 0 deletions type/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

#include <cstdint>
#include <cstring>
#include <span>
#include <string_view>
#include <utility>
#include <vector>

namespace ic::type {
Expand Down Expand Up @@ -208,6 +211,24 @@ struct FunctionType : internal_type::BasicType {
ParametersType parameters() const;
std::vector<Type> const& returns() const;

friend void NthPrint(auto& p, auto&fmt, FunctionType f) {
std::string_view separator = "(";
for (auto const& param : *f.parameters()) {
p.write(std::exchange(separator, ", "));
fmt(p, param.name);
p.write(": ");
fmt(p, param.type);
}
std::span returns = f.returns();
p.write(returns.size() != 1 ? ") -> (" : ") -> ");
separator = "";
for (auto const& r: f.returns()) {
p.write(std::exchange(separator, ", "));
fmt(p, r);
}
if (returns.size() != 1) { p.write(")"); }
}

private:
friend Type;
friend FunctionType Function(ParametersType, std::vector<Type>&&);
Expand Down Expand Up @@ -293,6 +314,8 @@ struct SliceType : internal_type::BasicType {
SliceType Slice(Type t);

struct GenericFunctionType : internal_type::BasicType {
void const* data() const;

private:
friend Type;
friend GenericFunctionType GenericFunction(void const* fn);
Expand Down
30 changes: 30 additions & 0 deletions type/type_system.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
syntax = "proto3";

package type;

message TypeProto {
enum Kind {
UNKNOWN = 0;
PRIMITIVE = 1;
POINTER = 2;
BUFFER_POINTER = 3;
SLICE = 4;
FUNCTION = 5;
PATTERN = 6;
}
Kind kind = 1;
uint32 index = 2;
}

message ParameterTypeProto {
TypeProto type = 1;
}

message FunctionTypeProto {
repeated ParameterTypeProto parameters = 1;
repeated TypeProto returns = 2;
}

message TypeSystem {
repeated FunctionTypeProto functions = 1;
}

0 comments on commit 727bd36

Please sign in to comment.