Skip to content

Commit df31b2c

Browse files
authored
Compile func args. (#37)
* Compile function args. * Compile function args. * Fix build. * Fix test. * Fix test. * Fix test. * clean up. Co-authored-by: Bowen Fu <missing>
1 parent f905413 commit df31b2c

File tree

5 files changed

+81
-34
lines changed

5 files changed

+81
-34
lines changed

include/lisp/vm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class VM;
8181

8282
class StackFrame
8383
{
84-
FunctionSymbol const& mFunc;
84+
FunctionSymbol const mFunc;
8585
std::vector<Object> mLocals;
8686
size_t mReturnAddress;
8787
public:

src/compiler.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void Compiler::compile(ExprPtr const& expr)
158158
if (auto appPtr = dynamic_cast<Application const*>(exprPtr))
159159
{
160160
auto nbOperands = appPtr->mOperands.size();
161-
OpCode opCode = [appPtr, nbOperands]
161+
int32_t opCode = [appPtr, nbOperands] () -> int32_t
162162
{
163163
auto opName = appPtr->mOperator->toString();
164164
if (opName == "+")
@@ -199,19 +199,38 @@ void Compiler::compile(ExprPtr const& expr)
199199
ASSERT(nbOperands == 1U);
200200
return kNOT;
201201
}
202-
FAIL_("Not supported yet!");
202+
return -1;
203203
}();
204-
if (nbOperands == 1)
204+
// primitive procedure
205+
if (opCode >= 0)
205206
{
207+
if (nbOperands == 1)
208+
{
209+
compile(appPtr->mOperands.at(0));
210+
instructions().push_back(static_cast<OpCode>(opCode));
211+
return;
212+
}
206213
compile(appPtr->mOperands.at(0));
207-
instructions().push_back(opCode);
214+
for (auto i = 1U; i < nbOperands; ++i)
215+
{
216+
compile(appPtr->mOperands.at(i));
217+
instructions().push_back(static_cast<OpCode>(opCode));
218+
}
208219
return;
209220
}
210-
compile(appPtr->mOperands.at(0));
211-
for (auto i = 1U; i < nbOperands; ++i)
221+
// lambda procedure.
212222
{
213-
compile(appPtr->mOperands.at(i));
214-
instructions().push_back(opCode);
223+
for (auto const& o : appPtr->mOperands)
224+
{
225+
compile(o);
226+
}
227+
compile(appPtr->mOperator);
228+
instructions().push_back(kCALL);
229+
auto bytes = integerToFourBytes(appPtr->mOperands.size());
230+
for (Byte i : bytes)
231+
{
232+
instructions().push_back(i);
233+
}
215234
}
216235
return;
217236
}

src/vm.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,15 @@ void VM::run()
149149
return;
150150
case kCALL:
151151
{
152-
uint32_t index = fourBytesToInteger<uint32_t>(&instructions()[mIp]);
152+
uint32_t nbParams = fourBytesToInteger<uint32_t>(&instructions()[mIp]);
153153
mIp += 4;
154154

155-
auto const& functionSymbol = std::get<FunctionSymbol>(mCode.constantPool.at(index));
155+
auto const functionSymbolPtr = std::get_if<FunctionSymbol>(&operandStack().top());
156+
ASSERT(functionSymbolPtr);
157+
auto const functionSymbol = *functionSymbolPtr;
158+
operandStack().pop();
159+
ASSERT(nbParams == functionSymbol.nbArgs());
160+
156161
std::vector<Object> params(functionSymbol.nbArgs() + functionSymbol.nbLocals());
157162
for (size_t i = functionSymbol.nbArgs(); i > 0; --i)
158163
{

test/lisp/testCompiler.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ TEST(Compiler, lambda0)
154154
TEST(Compiler, lambda1)
155155
{
156156
Compiler c{};
157-
ExprPtr num{new Number{5.5}};
158157
ExprPtr iVar{new Variable{"i"}};
159158
std::shared_ptr<Sequence> seq{new Sequence{{iVar}}};
160159
ExprPtr func{new Lambda{Params{std::make_pair(std::vector<std::string>{"i"}, false)}, seq}};
@@ -171,3 +170,49 @@ TEST(Compiler, lambda1)
171170
std::string output = testing::internal::GetCapturedStdout();
172171
EXPECT_EQ(output, "Function identity\n");
173172
}
173+
174+
TEST(Compiler, lambda2)
175+
{
176+
Compiler c{};
177+
ExprPtr num{new Number{5.5}};
178+
ExprPtr iVar{new Variable{"i"}};
179+
std::shared_ptr<Sequence> seq{new Sequence{{iVar}}};
180+
ExprPtr func{new Lambda{Params{std::make_pair(std::vector<std::string>{"i"}, false)}, seq}};
181+
auto const name = "identity";
182+
ExprPtr def{new Definition{name, func}};
183+
c.compile(def);
184+
ExprPtr var{new Variable{name}};
185+
ExprPtr app{new Application{var, {num}}};
186+
c.compile(app);
187+
ByteCode code = c.code();
188+
code.instructions.push_back(kPRINT);
189+
VM vm{code};
190+
testing::internal::CaptureStdout();
191+
vm.run();
192+
std::string output = testing::internal::GetCapturedStdout();
193+
EXPECT_EQ(output, "5.5\n");
194+
}
195+
196+
TEST(Compiler, lambda3)
197+
{
198+
Compiler c{};
199+
ExprPtr num{new Number{5.5}};
200+
ExprPtr iVar{new Variable{"i"}};
201+
ExprPtr plusVar{new Variable{"+"}};
202+
ExprPtr doubleApp{new Application{plusVar, {iVar, iVar}}};
203+
std::shared_ptr<Sequence> seq{new Sequence{{doubleApp}}};
204+
ExprPtr func{new Lambda{Params{std::make_pair(std::vector<std::string>{"i"}, false)}, seq}};
205+
auto const name = "double";
206+
ExprPtr def{new Definition{name, func}};
207+
c.compile(def);
208+
ExprPtr var{new Variable{name}};
209+
ExprPtr app{new Application{var, {num}}};
210+
c.compile(app);
211+
ByteCode code = c.code();
212+
code.instructions.push_back(kPRINT);
213+
VM vm{code};
214+
testing::internal::CaptureStdout();
215+
vm.run();
216+
std::string output = testing::internal::GetCapturedStdout();
217+
EXPECT_EQ(output, "11\n");
218+
}

test/lisp/testVm.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,3 @@ TEST(VM, str)
3030
std::string output = testing::internal::GetCapturedStdout();
3131
EXPECT_EQ(output, "some str: 123\n");
3232
}
33-
34-
// TEST(VM, func)
35-
// {
36-
// std::vector<Byte> const instructions = {kICONST, 0, 0, 0, 11, kCALL, 0, 0, 0, 0, kHALT, kGET_LOCAL, 0, 0, 0, 0, kPRINT};
37-
// std::vector<Object> const constPool = {FunctionSymbol{"main", 1, 1, 11}};
38-
// VM vm{ByteCode{instructions, constPool}};
39-
// testing::internal::CaptureStdout();
40-
// vm.run();
41-
// std::string output = testing::internal::GetCapturedStdout();
42-
// EXPECT_EQ(output, "11\n");
43-
// }
44-
45-
// TEST(VM, func2)
46-
// {
47-
// std::vector<Byte> const instructions = {kICONST, 0, 0, 0, 11, kCALL, 0, 0, 0, 0, kPRINT, kHALT, kGET_LOCAL, 0, 0, 0, 0, kICONST, 0, 0, 0, 2, kIADD, kSET_LOCAL, 0, 0, 0, 1, kGET_LOCAL, 0, 0, 0, 1, kRET};
48-
// std::vector<Object> const constPool = {FunctionSymbol{"id", 1, 1, 12}};
49-
// VM vm{ByteCode{instructions, constPool}};
50-
// testing::internal::CaptureStdout();
51-
// vm.run();
52-
// std::string output = testing::internal::GetCapturedStdout();
53-
// EXPECT_EQ(output, "13\n");
54-
// }

0 commit comments

Comments
 (0)