Skip to content
This repository was archived by the owner on Oct 12, 2026. It is now read-only.

Commit a1247ef

Browse files
committed
feat: added signature for all the native functions
1 parent d6ccebc commit a1247ef

7 files changed

Lines changed: 170 additions & 75 deletions

File tree

‎include/lbd/runtime/interpreter.h‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
#include <optional>
55
#include <string>
66
#include <variant>
7+
#include <lbd/options.h>
78
#include <lbd/frontend/ast.h>
89
#include <lbd/frontend/parser.h>
9-
#include <lbd/options.h>
1010

1111
namespace runtime::type {
1212
struct FunctionType;
@@ -66,8 +66,7 @@ namespace runtime {
6666
using Implementation = std::function<std::pair<Value, ResultOptions>(
6767
const std::vector<std::shared_ptr<Thunk> > &, const std::shared_ptr<Environment> &)>;
6868

69-
NativeFunction(const std::string &name, const std::shared_ptr<type::FunctionType> &signature,
70-
const Implementation &implementation);
69+
NativeFunction(std::string name, std::shared_ptr<type::FunctionType> signature, Implementation implementation);
7170

7271
[[nodiscard]] std::string getName() const;
7372

‎include/lbd/runtime/type.h‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

3-
#include <string>
43
#include <memory>
4+
#include <string>
55
#include <vector>
66

77
/// These are runtime-types different from frontend::type.
@@ -11,6 +11,8 @@ namespace runtime {
1111
struct Value;
1212
}
1313

14+
// TODO: Maybe move instead of copying the reference.
15+
1416
namespace runtime::type {
1517
enum class TypeTag {
1618
Float,
@@ -25,21 +27,24 @@ namespace runtime::type {
2527

2628
std::string typeTagToString(TypeTag tag);
2729

30+
// TODO: Implement move-constructor and possibly move-assignment-operator.
2831
struct Type {
2932
virtual ~Type() = default;
3033

31-
[[nodiscard]] virtual bool matches(const Value &value) const;
34+
[[nodiscard]] virtual bool matches(const Value &value) const = 0;
3235

33-
[[nodiscard]] virtual bool equals(const Type &otherType) const;
36+
[[nodiscard]] virtual bool equals(const Type &otherType) const = 0;
3437

3538
[[nodiscard]] virtual std::string toString() const = 0;
3639

37-
[[nodiscard]] virtual bool isCallable() const;
40+
[[nodiscard]] virtual bool isCallable() const = 0;
3841
};
3942

4043
struct SimpleType final : Type {
4144
explicit SimpleType(TypeTag tag);
4245

46+
~SimpleType() override = default;
47+
4348
[[nodiscard]] bool matches(const Value &value) const override;
4449

4550
[[nodiscard]] bool equals(const Type &otherType) const override;
@@ -55,6 +60,8 @@ namespace runtime::type {
5560
struct ListType final : Type {
5661
explicit ListType(const std::shared_ptr<Type> &elementType);
5762

63+
~ListType() override = default;
64+
5865
[[nodiscard]] bool matches(const Value &value) const override;
5966

6067
[[nodiscard]] bool equals(const Type &otherType) const override;
@@ -68,10 +75,12 @@ namespace runtime::type {
6875
};
6976

7077
struct FunctionType final : Type {
71-
// TODO: Add support for void return-type.
78+
// TODO: Add support for void return-type. Maybe if return-type is nullptr: then it is void.
7279
explicit FunctionType(const std::vector<std::shared_ptr<Type> > &argumentTypes,
7380
const std::shared_ptr<Type> &returnType, bool isVariadic = false);
7481

82+
~FunctionType() override = default;
83+
7584
[[nodiscard]] bool matches(const Value &value) const override;
7685

7786
[[nodiscard]] bool equals(const Type &otherType) const override;

‎src/runtime/builtin-modules/builtin_module_core.cpp‎

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ namespace runtime::builtins {
55
// Prints Argument to stdout and returns 0.
66
NativeFunction makePrint() {
77
const std::string name = "print";
8+
const auto signature = functionType(
9+
{simpleType(type::TypeTag::Any)},
10+
nullptr,
11+
true
12+
);
813
return {
9-
-1, name, [](const std::vector<std::shared_ptr<Thunk> > &arguments,
10-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
14+
name, signature, [](const std::vector<std::shared_ptr<Thunk> > &arguments,
15+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
1116
for (auto &argument: arguments) {
1217
const Value &value = argument->force();
1318
std::cout << value;
@@ -19,9 +24,13 @@ namespace runtime::builtins {
1924

2025
NativeFunction makeAdd() {
2126
const std::string name = "add";
27+
const auto signature = functionType(
28+
{simpleType(type::TypeTag::Float), simpleType(type::TypeTag::Float)},
29+
simpleType(type::TypeTag::Float)
30+
);
2231
return {
23-
2, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
24-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
32+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
33+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
2534
const Value &value1 = arguments[0]->force();
2635
const Value &value2 = arguments[1]->force();
2736
if (!std::holds_alternative<double>(value1) || !std::holds_alternative<double>(value2)) {
@@ -36,9 +45,13 @@ namespace runtime::builtins {
3645

3746
NativeFunction makeSub() {
3847
const std::string name = "sub";
48+
const auto signature = functionType(
49+
{simpleType(type::TypeTag::Float), simpleType(type::TypeTag::Float)},
50+
simpleType(type::TypeTag::Float)
51+
);
3952
return {
40-
2, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
41-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
53+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
54+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
4255
const Value &value1 = arguments[0]->force();
4356
const Value &value2 = arguments[1]->force();
4457
if (!std::holds_alternative<double>(value1) || !std::holds_alternative<double>(value2)) {
@@ -53,9 +66,13 @@ namespace runtime::builtins {
5366

5467
NativeFunction makeMul() {
5568
const std::string name = "mul";
69+
const auto signature = functionType(
70+
{simpleType(type::TypeTag::Float), simpleType(type::TypeTag::Float)},
71+
simpleType(type::TypeTag::Float)
72+
);
5673
return {
57-
2, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
58-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
74+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
75+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
5976
const Value &value1 = arguments[0]->force();
6077
const Value &value2 = arguments[1]->force();
6178
if (!std::holds_alternative<double>(value1) || !std::holds_alternative<double>(value2)) {
@@ -70,9 +87,13 @@ namespace runtime::builtins {
7087

7188
NativeFunction makeCmp() {
7289
const std::string name = "cmp";
90+
const auto signature = functionType(
91+
{simpleType(type::TypeTag::Float), simpleType(type::TypeTag::Float)},
92+
simpleType(type::TypeTag::Float)
93+
);
7394
return {
74-
2, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
75-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
95+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
96+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
7697
const Value &value1 = arguments[0]->force();
7798
const Value &value2 = arguments[1]->force();
7899
if (!std::holds_alternative<double>(value1) || !std::holds_alternative<double>(value2)) {
@@ -89,9 +110,14 @@ namespace runtime::builtins {
89110

90111
NativeFunction makeIfZero() {
91112
const std::string name = "if_zero";
113+
// TODO: The return-type should be either argument-1 or argument-2.
114+
const auto signature = functionType(
115+
{simpleType(type::TypeTag::Float), simpleType(type::TypeTag::Any), simpleType(type::TypeTag::Any)},
116+
simpleType(type::TypeTag::Any)
117+
);
92118
return {
93-
3, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
94-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
119+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
120+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
95121
const Value &conditionValue = arguments[0]->force();
96122
if (!std::holds_alternative<double>(conditionValue)) {
97123
optionsValue.logger.error({}, "runtime error: wrong arguments provided to native function ", name,
@@ -110,9 +136,13 @@ namespace runtime::builtins {
110136

111137
NativeFunction makeParseFloat() {
112138
const std::string name = "parse_float";
139+
const auto signature = functionType(
140+
{simpleType(type::TypeTag::String)},
141+
simpleType(type::TypeTag::Float)
142+
);
113143
return {
114-
1, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
115-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
144+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
145+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
116146
const Value &argument0 = arguments[0]->force();
117147
if (!std::holds_alternative<std::string>(argument0)) {
118148
optionsValue.logger.error({},
@@ -121,7 +151,7 @@ namespace runtime::builtins {
121151
" signature: String -> Float\n"
122152
"runtime error: expected String got ", argument0);
123153
}
124-
const std::string &argumentString = std::get<std::string>(argument0);
154+
const auto &argumentString = std::get<std::string>(argument0);
125155
try {
126156
const double value = std::stod(argumentString);
127157
return {Value{value}, ResultOptions{}};

‎src/runtime/builtin-modules/builtin_module_io.cpp‎

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@
33
#include <lbd/runtime/builtin-modules/builtin_module_io.h>
44

55
namespace runtime::builtins {
6+
// TODO: Move print to io module.
7+
68
NativeFunction makeSlurpFile() {
79
const std::string name = "slurp_file";
10+
const auto signature = functionType(
11+
{simpleType(type::TypeTag::String)},
12+
simpleType(type::TypeTag::String)
13+
);
814
return {
9-
1, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
10-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
15+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
16+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
1117
const Value &argument0 = arguments[0]->force();
1218
if (!std::holds_alternative<std::string>(argument0)) {
1319
optionsValue.logger.error({},
14-
"runtime error: wrong arguments provided to native function ", name,
15-
"\n", name, " signature: String -> String\n"
16-
"runtime error: expected <String> got ", argument0);
20+
"runtime error: wrong arguments provided to native function ", name,
21+
"\n", name, " signature: String -> String\n"
22+
"runtime error: expected <String> got ", argument0);
1723
}
1824
const auto &path = std::get<std::string>(argument0);
1925
std::ifstream file(path, std::ios::in | std::ios::binary);
@@ -27,15 +33,19 @@ namespace runtime::builtins {
2733

2834
NativeFunction makeLines() {
2935
const std::string name = "lines";
36+
const auto signature = functionType(
37+
{simpleType(type::TypeTag::String)},
38+
listType(simpleType(type::TypeTag::String))
39+
);
3040
return {
31-
1, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
32-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
41+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
42+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
3343
const Value &argument0 = arguments[0]->force();
3444
if (!std::holds_alternative<std::string>(argument0)) {
3545
optionsValue.logger.error({},
36-
"runtime error: wrong arguments provided to native function ", name,
37-
"\n", name, " signature: String -> List<String>\n"
38-
"runtime error: expected <String> got ", argument0);
46+
"runtime error: wrong arguments provided to native function ", name,
47+
"\n", name, " signature: String -> List<String>\n"
48+
"runtime error: expected <String> got ", argument0);
3949
}
4050
const auto input = std::get<std::string>(argument0);
4151
// Normalize all line endings to '\n'
@@ -66,25 +76,29 @@ namespace runtime::builtins {
6676

6777
NativeFunction makeSplit() {
6878
const std::string name = "split";
79+
const auto signature = functionType(
80+
{simpleType(type::TypeTag::String), simpleType(type::TypeTag::String)},
81+
listType(simpleType(type::TypeTag::String))
82+
);
6983
return {
70-
2, name, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
71-
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
84+
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
85+
const std::shared_ptr<Environment> &) -> std::pair<Value, ResultOptions> {
7286
const Value &argument0 = arguments[0]->force(); // string
7387
if (!std::holds_alternative<std::string>(argument0)) {
7488
optionsValue.logger.error({}, "runtime error: wrong arguments provided to native function ", name,
75-
"\n", name,
76-
" signature: String -> String -> List<String>""\n"
77-
"runtime error: expected <String> got ", argument0);
89+
"\n", name,
90+
" signature: String -> String -> List<String>""\n"
91+
"runtime error: expected <String> got ", argument0);
7892
}
7993
const Value &argument1 = arguments[1]->force(); // delimiter
8094
if (!std::holds_alternative<std::string>(argument1)) {
8195
optionsValue.logger.error({}, "runtime error: wrong arguments provided to native function ", name,
82-
"\n", name,
83-
" signature: String -> String -> List""\n"
84-
"runtime error: expected <String> got ", argument1);
96+
"\n", name,
97+
" signature: String -> String -> List""\n"
98+
"runtime error: expected <String> got ", argument1);
8599
}
86-
const std::string &input = std::get<std::string>(argument0);
87-
const std::string &delimiter = std::get<std::string>(argument1);
100+
const auto &input = std::get<std::string>(argument0);
101+
const auto &delimiter = std::get<std::string>(argument1);
88102
if (delimiter.empty()) {
89103
optionsValue.logger.error({}, "runtime error: delimiter for ", name, " cannot be empty");
90104
}

0 commit comments

Comments
 (0)