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

Commit fba858b

Browse files
committed
fix: resolve bugs in runtime type checking
1 parent 68ad5b9 commit fba858b

7 files changed

Lines changed: 50 additions & 59 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
> Functional Programming Language based on [Lambda Calculus](https://en.wikipedia.org/wiki/Lambda_calculus) highly inspired by this video [Programming with Math | The Lambda Calculus - Eyesomorphic](https://youtu.be/ViPNHMSUcog) made from scratch, entirely in `C++`.
1+
> Functional Programming Language based on [Lambda Calculus](https://en.wikipedia.org/wiki/Lambda_calculus) highly
2+
> inspired by this video [Programming with Math | The Lambda Calculus - Eyesomorphic](https://youtu.be/ViPNHMSUcog) made
3+
> from scratch, entirely in `C++`.
24
35
---
46

@@ -121,4 +123,6 @@ lbd [options]
121123

122124
- TODO: Add better examples (e.g., Advent of Code snippets).
123125
- TODO: CI/CD for testing.
124-
- TODO: Fix tests output in README.
126+
- TODO: Fix tests output in README.
127+
- TODO: Step debug kind of functionality in REPL. Inside REPL, while loading a file, load one expression at a time and
128+
provide user with some feedback and actions to perform.

‎include/lbd/runtime/builtins.h‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ namespace runtime::builtins {
1414
return std::make_shared<type::SimpleType>(tag);
1515
}
1616

17-
inline TypePointer listType(TypePointer elementType) {
18-
return std::make_shared<type::ListType>(elementType);
17+
inline TypePointer listType() {
18+
return std::make_shared<type::ListType>();
1919
}
2020

21-
inline std::shared_ptr<type::FunctionType> functionType(std::vector<TypePointer> argumentTypes,
22-
TypePointer returnType,
21+
inline std::shared_ptr<type::FunctionType> functionType(const std::vector<TypePointer> &argumentTypes,
22+
const TypePointer &returnType,
2323
bool isVariadic = false) {
24-
return std::make_shared<type::FunctionType>(std::move(argumentTypes), std::move(returnType), isVariadic);
24+
return std::make_shared<type::FunctionType>(argumentTypes, returnType, isVariadic);
2525
}
2626

2727
// TODO: Move the definitions to source-file.

‎include/lbd/runtime/type.h‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ namespace runtime::type {
6060

6161
// TODO: List should not have element-type, as we can add any type to it.
6262
struct ListType final : Type {
63-
explicit ListType(const std::shared_ptr<Type> &elementType);
64-
6563
~ListType() override = default;
6664

6765
[[nodiscard]] bool matches(const Value &value) const override;
@@ -71,9 +69,6 @@ namespace runtime::type {
7169
[[nodiscard]] std::string toString() const override;
7270

7371
[[nodiscard]] bool isCallable() const override;
74-
75-
private:
76-
std::shared_ptr<Type> elementType;
7772
};
7873

7974
struct FunctionType final : Type {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace runtime::builtins {
3535
const std::string name = "lines";
3636
const auto signature = functionType(
3737
{simpleType(type::TypeTag::String)},
38-
listType(simpleType(type::TypeTag::String))
38+
listType()
3939
);
4040
return {
4141
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
@@ -78,7 +78,7 @@ namespace runtime::builtins {
7878
const std::string name = "split";
7979
const auto signature = functionType(
8080
{simpleType(type::TypeTag::String), simpleType(type::TypeTag::String)},
81-
listType(simpleType(type::TypeTag::String))
81+
listType()
8282
);
8383
return {
8484
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace runtime::builtins {
3232
const std::string name = "list";
3333
const auto signature = functionType(
3434
{simpleType(type::TypeTag::Any)},
35-
listType(simpleType(type::TypeTag::Any)),
35+
listType(),
3636
true
3737
);
3838
return {
@@ -50,7 +50,7 @@ namespace runtime::builtins {
5050
NativeFunction makeListSize() {
5151
const std::string name = "list_size";
5252
const auto signature = functionType(
53-
{listType(simpleType(type::TypeTag::Any))},
53+
{listType()},
5454
simpleType(type::TypeTag::Float)
5555
);
5656
return {
@@ -73,7 +73,7 @@ namespace runtime::builtins {
7373
NativeFunction makeListGet() {
7474
const std::string name = "list_get";
7575
const auto signature = functionType(
76-
{listType(simpleType(type::TypeTag::Any)), simpleType(type::TypeTag::Float)},
76+
{listType(), simpleType(type::TypeTag::Float)},
7777
simpleType(type::TypeTag::Any)
7878
);
7979
return {
@@ -105,7 +105,7 @@ namespace runtime::builtins {
105105
NativeFunction makeListRemove() {
106106
const std::string name = "list_remove";
107107
const auto signature = functionType(
108-
{listType(simpleType(type::TypeTag::Any)), simpleType(type::TypeTag::Float)},
108+
{listType(), simpleType(type::TypeTag::Float)},
109109
simpleType(type::TypeTag::Any)
110110
);
111111
return {
@@ -139,7 +139,7 @@ namespace runtime::builtins {
139139
NativeFunction makeListAppend() {
140140
const std::string name = "list_append";
141141
const auto signature = functionType(
142-
{listType(simpleType(type::TypeTag::Any)), simpleType(type::TypeTag::Any)},
142+
{listType(), simpleType(type::TypeTag::Any)},
143143
nullptr
144144
);
145145
return {
@@ -152,9 +152,9 @@ namespace runtime::builtins {
152152
" signature: List -> Any -> List""\n"
153153
"runtime error: expected <List> got ", argument0);
154154
}
155-
auto list_v = std::get<std::shared_ptr<List> >(argument0);
156-
listAppend(list_v, arguments[1]->force());
157-
return std::make_pair(Value{list_v}, ResultOptions{});
155+
auto list = std::get<std::shared_ptr<List> >(argument0);
156+
listAppend(list, arguments[1]->force());
157+
return std::make_pair(Value{list}, ResultOptions{});
158158
}
159159
};
160160
}
@@ -166,9 +166,9 @@ namespace runtime::builtins {
166166
const auto signature = functionType(
167167
{
168168
functionType({simpleType(type::TypeTag::Any)}, simpleType(type::TypeTag::Any)),
169-
listType(simpleType(type::TypeTag::Any))
169+
listType()
170170
},
171-
listType(simpleType(type::TypeTag::Any))
171+
listType()
172172
);
173173
return {
174174
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
@@ -201,8 +201,8 @@ namespace runtime::builtins {
201201
NativeFunction makeTranspose() {
202202
const std::string name = "transpose";
203203
const auto signature = functionType(
204-
{listType(listType(simpleType(type::TypeTag::Any)))},
205-
listType(listType(simpleType(type::TypeTag::Any)))
204+
{listType()},
205+
listType()
206206
);
207207
return {
208208
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
@@ -250,8 +250,8 @@ namespace runtime::builtins {
250250
NativeFunction makeSort() {
251251
const std::string name = "sort";
252252
const auto signature = functionType(
253-
{listType(simpleType(type::TypeTag::Float))},
254-
listType(simpleType(type::TypeTag::Float))
253+
{listType()},
254+
listType()
255255
);
256256
return {
257257
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
@@ -290,8 +290,8 @@ namespace runtime::builtins {
290290
NativeFunction makeZip() {
291291
const std::string name = "zip";
292292
const auto signature = functionType(
293-
{listType(listType(simpleType(type::TypeTag::Any)))},
294-
listType(listType(simpleType(type::TypeTag::Any)))
293+
{listType()},
294+
listType()
295295
);
296296
return {
297297
name, signature, [name](const std::vector<std::shared_ptr<Thunk> > &arguments,
@@ -344,7 +344,7 @@ namespace runtime::builtins {
344344
{
345345
functionType({simpleType(type::TypeTag::Any), simpleType(type::TypeTag::Any)},
346346
simpleType(type::TypeTag::Any)),
347-
listType(simpleType(type::TypeTag::Any)),
347+
listType(),
348348
simpleType(type::TypeTag::Any)
349349
},
350350
simpleType(type::TypeTag::Any)

‎src/runtime/interpreter.cpp‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,13 @@ namespace runtime {
329329
// }
330330
auto [resultantValue_, resultOptions] = nativeFunction.getImplementation()(
331331
slice, callSiteEnvironment);
332-
// if (!signature.matchesReturnType(resultantValue_)) {
333-
// optionsValue.logger.error(callLocation,
334-
// "internal error: expected native-function to return ",
335-
// signature.getReturnType().toString(), ", but got ",
336-
// type::typeFromValue(resultantValue_)->toString());
337-
// // TODO: possibly not create an additional type-object just for printing.
338-
// }
332+
if (!signature.matchesReturnType(resultantValue_)) {
333+
optionsValue.logger.error(callLocation,
334+
"internal error: expected native-function ", nativeFunction.getName(),
335+
" to return ", signature.getReturnType().toString(), ", but got ",
336+
type::typeFromValue(resultantValue_)->toString());
337+
// TODO: possibly not create an additional type-object just for printing.
338+
}
339339
resultantValue = resultantValue_;
340340
globalResultOptions.interpolate(resultOptions);
341341
index += arity;

‎src/runtime/type.cpp‎

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,30 +65,16 @@ namespace runtime::type {
6565
return false;
6666
}
6767

68-
ListType::ListType(const std::shared_ptr<Type> &elementType) : elementType(elementType) {
69-
}
70-
7168
bool ListType::matches(const Value &value) const {
72-
if (typeTagFromValue(value) != TypeTag::Any) {
73-
return false;
74-
}
75-
auto &[elements] = *std::get<std::shared_ptr<List> >(value);
76-
return std::all_of(elements.begin(), elements.end(), [&](const auto &element) {
77-
return elementType->matches(element);
78-
});
69+
return typeTagFromValue(value) == TypeTag::List;
7970
}
8071

8172
bool ListType::equals(const Type &otherType) const {
82-
if (const auto *otherListType = dynamic_cast<const ListType *>(&otherType)) {
83-
return elementType && otherListType->elementType && elementType->equals(*otherListType->elementType);
84-
}
85-
return false;
73+
return dynamic_cast<const ListType *>(&otherType) != nullptr;
8674
}
8775

8876
std::string ListType::toString() const {
89-
std::ostringstream outputStringStream;
90-
outputStringStream << "[" << elementType->toString() << "]";
91-
return outputStringStream.str();
77+
return "[]";
9278
}
9379

9480
bool ListType::isCallable() const {
@@ -135,7 +121,9 @@ namespace runtime::type {
135121
}
136122

137123
bool FunctionType::matchesReturnType(const Value &value) const {
138-
return returnType && returnType->matches(value);
124+
// If the return-type is nullptr, i.e., return-type is void.
125+
// Do not perform any check in such scenario.
126+
return returnType ? returnType->matches(value) : true;
139127
}
140128

141129
bool FunctionType::equals(const Type &otherType) const {
@@ -155,7 +143,11 @@ namespace runtime::type {
155143
return false;
156144
}
157145
}
158-
return returnType && otherFunctionType->returnType && returnType->equals(*otherFunctionType->returnType);
146+
if (returnType) {
147+
return otherFunctionType->returnType && returnType->equals(*otherFunctionType->returnType);
148+
}
149+
// Return-Type is nullptr i.e., void.
150+
return true;
159151
}
160152

161153
std::string FunctionType::toString() const {
@@ -198,8 +190,8 @@ namespace runtime::type {
198190
} else if constexpr (std::is_same_v<T, std::shared_ptr<NativeFunction> >) {
199191
const auto &nativeFunction = *std::get<std::shared_ptr<NativeFunction> >(value);
200192
return std::make_shared<FunctionType>(*nativeFunction.getSignature());
201-
} else if constexpr (std::is_same_v<T, std::shared_ptr<NativeFunction> >) {
202-
return std::make_shared<ListType>(std::make_shared<SimpleType>(TypeTag::Any));
193+
} else if constexpr (std::is_same_v<T, std::shared_ptr<List> >) {
194+
return std::make_shared<ListType>();
203195
} else {
204196
return std::make_shared<SimpleType>(TypeTag::Any);
205197
}

0 commit comments

Comments
 (0)