Implement a map function that works on lists
This commit is contained in:
parent
06149c3d61
commit
049aeef62f
3 changed files with 56 additions and 1 deletions
|
@ -161,6 +161,60 @@ Result<StackFrame> stdlib_size(const StackFrame& stack) {
|
|||
return res.ret(0);
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_map(const StackFrame& stack_param) {
|
||||
auto stack = TRY(stack_param.copy());
|
||||
auto params = TRY(stack.get(0));
|
||||
auto stack_size = TRY(stack.size());
|
||||
|
||||
auto fun = TRY(params.get(1));
|
||||
|
||||
if (stack_size == 1) {
|
||||
// This is the first call, need to set up arguments on the stack
|
||||
auto collection = TRY(params.get(0));
|
||||
|
||||
auto num_params = TRY(params.size());
|
||||
if (num_params != 2) return ERROR(ArgumentCountMismatch);
|
||||
|
||||
if (!collection.is<Pair>()) return ERROR(TypeMismatch);
|
||||
|
||||
// Result accumulator will contain nil value initially
|
||||
auto nil = Value(TRY(Nil::create()));
|
||||
stack = TRY(stack.set(1, nil));
|
||||
|
||||
// Remaining elements in the collection
|
||||
stack = TRY(stack.set(2, TRY(collection.rest())));
|
||||
|
||||
stack = TRY(stack.set(3, fun));
|
||||
stack = TRY(stack.set(4, TRY(collection.first())));
|
||||
|
||||
return TRY(stack.call(fun, 3, 5));
|
||||
}
|
||||
|
||||
auto accumulator = TRY(stack.get(1));
|
||||
auto remaining = TRY(stack.get(2));
|
||||
auto fun_result = TRY(stack.get(3));
|
||||
|
||||
accumulator = Value(TRY(Pair::create(fun_result, accumulator)));
|
||||
|
||||
stack = TRY(stack.set(1, accumulator));
|
||||
|
||||
if (!remaining.is<Nil>()) {
|
||||
stack = TRY(stack.set(2, TRY(remaining.rest())));
|
||||
stack = TRY(stack.set(3, fun));
|
||||
stack = TRY(stack.set(4, TRY(remaining.first())));
|
||||
|
||||
return TRY(stack.call(fun, 3, 5));
|
||||
}
|
||||
|
||||
accumulator = TRY(reverse(accumulator));
|
||||
|
||||
auto res = TRY(stack.set(0, accumulator));
|
||||
res = TRY(res.ret(0));
|
||||
res = TRY(res.incpc());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define STDLIB_FUNCTION(name, id) \
|
||||
[(uint64_t)StdlibFunctionId::id] = {#name, StdlibFunctionId::id, \
|
||||
stdlib_##name}
|
||||
|
@ -177,6 +231,7 @@ static StdlibFunctionEntry function_entries[] = {
|
|||
STDLIB_FUNCTION(get, Get),
|
||||
STDLIB_FUNCTION(srcloc, SrcLoc),
|
||||
STDLIB_FUNCTION(size, Size),
|
||||
STDLIB_FUNCTION(map, Map),
|
||||
[(uint64_t)StdlibFunctionId::Max] = {0, StdlibFunctionId::Max,
|
||||
stdlib_unknown},
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ enum class StdlibFunctionId : uint64_t {
|
|||
Get,
|
||||
SrcLoc,
|
||||
Size,
|
||||
Map,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
|
|
@ -283,7 +283,6 @@ Result<void> VM::step_native() {
|
|||
auto fun_id = fun.to<StdlibFunction>()->fun_id();
|
||||
|
||||
_stack = TRY(call_stdlib_function(fun_id, _stack));
|
||||
_stack = TRY(_stack.incpc());
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue