Skip to content

Commit

Permalink
[Methods] Add initial groundwork
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinjoseph1995 committed May 6, 2023
1 parent 5b9bc17 commit c37c05b
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 17 deletions.
3 changes: 0 additions & 3 deletions .clangd
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
CompileFlags:
Remove: [-std=gnu++23]
Add: [-std=gnu++2b -stdlib=libc++]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ external
compile_commands.json
.cache/
.vscode/*
.clangd
8 changes: 4 additions & 4 deletions data/test.lox
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class MyClass {}
var my_instance = MyClass();
my_instance.field1 = 10;
print my_instance.field1;
class Toast{
function() {
}
}
3 changes: 3 additions & 0 deletions src/chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ auto Disassemble_instruction(Chunk const& chunk, uint64_t offset) -> uint64_t
offset += 3;
return offset;
}
case OP_METHOD:
fmt::print("{:#08x} OP_METHOD\n", offset);
return ++offset;
}
LOX_ASSERT(false);
}
Expand Down
3 changes: 2 additions & 1 deletion src/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ enum OpCode : uint8_t {
OP_CLOSE_UPVALUE,
OP_CLASS,
OP_GET_PROPERTY,
OP_SET_PROPERTY
OP_SET_PROPERTY,
OP_METHOD
};

static constexpr auto MAX_INDEX_SIZE = std::numeric_limits<uint16_t>::max();
Expand Down
50 changes: 42 additions & 8 deletions src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
#include <limits>
#include <optional>
#include <ranges>
#include <string_view>

#include "chunk.h"
#include "error.h"
#include "fmt/core.h"
#include "heap.h"
#include "object.h"
#include "scanner.h"
#include "value.h"

Expand Down Expand Up @@ -317,13 +319,41 @@ auto Compiler::classDeclaration() -> void
m_parser_state.ReportError(m_parser_state.PreviousToken()->line_number, GetTokenSpan(m_parser_state.PreviousToken().value()), "Expected class name after the class keyword");
return;
}
auto constant_index_result = identifierConstant(m_parser_state.PreviousToken().value());
auto class_identifier_token = m_parser_state.PreviousToken().value();
auto constant_index_result = identifierConstant(class_identifier_token);
declareVariable();
emitByte(OP_CLASS);
emitIndex(constant_index_result);
defineVariable(constant_index_result);
m_parser_state.Consume(TokenType::LEFT_BRACE);
m_parser_state.Consume(TokenType::RIGHT_BRACE);

// Emit instructions to leave the class on top of the stack
std::string_view class_name { m_source->GetSource().data() + class_identifier_token.start, class_identifier_token.length };
this->namedVariable(class_name, false);

if (not m_parser_state.Consume(TokenType::LEFT_BRACE)) {
m_parser_state.ReportError(m_parser_state.PreviousToken()->line_number,
GetTokenSpan(*m_parser_state.PreviousToken()), "Expected \"{\" after the class identifier");
}
while (m_parser_state.CurrentToken()->type != TokenType::RIGHT_BRACE && m_parser_state.CurrentToken()->type != TokenType::TOKEN_EOF) {
method();
}
if (not m_parser_state.Consume(TokenType::RIGHT_BRACE)) {
m_parser_state.ReportError(m_parser_state.PreviousToken()->line_number,
GetTokenSpan(*m_parser_state.PreviousToken()), "Expected \"}\" to end the class declaration");
}
emitByte(OP_POP); // Pop the class of the stack
}

auto Compiler::method() -> void
{
if (!m_parser_state.Consume(TokenType::IDENTIFIER)) {
m_parser_state.ReportError(m_parser_state.PreviousToken()->line_number, GetTokenSpan(m_parser_state.PreviousToken().value()), "Expected method identifier");
return;
}
auto constant_index_result = identifierConstant(m_parser_state.PreviousToken().value());
function(); // When executed will leave a closure on top of the stack
emitByte(OP_METHOD);
emitIndex(constant_index_result);
}

auto Compiler::declaration() -> void
Expand Down Expand Up @@ -520,12 +550,8 @@ auto Compiler::variableDeclaration() -> void
defineVariable(identifier_index_in_constant_pool.value());
}

auto Compiler::variable(bool can_assign) -> void
auto Compiler::namedVariable(std::string_view new_local_identifier_name, bool can_assign) -> void
{
auto start_offset = static_cast<std::string::difference_type>(m_parser_state.PreviousToken().value().start);
auto end_offset = start_offset + static_cast<std::string::difference_type>(m_parser_state.PreviousToken()->length);
std::string_view new_local_identifier_name { m_source->GetSource().begin() + start_offset, m_source->GetSource().begin() + end_offset };

OpCode set_op;
OpCode get_op;
uint16_t index;
Expand Down Expand Up @@ -560,6 +586,14 @@ auto Compiler::variable(bool can_assign) -> void
}
}

auto Compiler::variable(bool can_assign) -> void
{
auto start_offset = static_cast<std::string::difference_type>(m_parser_state.PreviousToken().value().start);
auto end_offset = start_offset + static_cast<std::string::difference_type>(m_parser_state.PreviousToken()->length);
std::string_view new_local_identifier_name { m_source->GetSource().begin() + start_offset, m_source->GetSource().begin() + end_offset };
namedVariable(new_local_identifier_name, can_assign);
}

auto Compiler::identifierConstant(Token const& token) -> uint16_t
{
LOX_ASSERT(token.type == TokenType::IDENTIFIER);
Expand Down
3 changes: 3 additions & 0 deletions src/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <array>
#include <cstdint>
#include <optional>
#include <string_view>

// clang-format off
enum Precedence {
Expand Down Expand Up @@ -135,6 +136,7 @@ class Compiler {
auto returnStatement() -> void;
auto classDeclaration() -> void;
auto function() -> void;
auto method() -> void;
auto setFunctionName() -> void;
auto ifStatement() -> void;
auto whileStatement() -> void;
Expand Down Expand Up @@ -168,6 +170,7 @@ class Compiler {
auto literal(bool can_assign) -> void;
auto number(bool can_assign) -> void;
auto variable(bool can_assign) -> void;
auto namedVariable(std::string_view identifier_name, bool can_assign) -> void;
auto string(bool can_assign) -> void;
};

Expand Down
8 changes: 7 additions & 1 deletion src/heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,6 @@ auto Heap::blackenObject(Object* object) -> void
switch (object->type) {
case ObjectType::STRING:
case ObjectType::NATIVE_FUNCTION:
case ObjectType::CLASS:
break; // No outgoing references nothing to do
case ObjectType::UPVALUE: {
auto upvalue = static_cast<UpvalueObject*>(object);
Expand All @@ -350,6 +349,13 @@ auto Heap::blackenObject(Object* object) -> void
}
break;
}
case ObjectType::CLASS: {
auto class_obj_ptr = static_cast<ClassObject*>(object);
for (auto& [_, method] : class_obj_ptr->methods) {
markRoot(method);
}
break;
}
case ObjectType::INSTANCE: {
auto instance = static_cast<InstanceObject*>(object);
for (auto const& [_, value] : instance->fields) {
Expand Down
1 change: 1 addition & 0 deletions src/native_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#ifndef LOX_CPP_NATIVE_FUNCTION_H
#define LOX_CPP_NATIVE_FUNCTION_H

#include "error.h"
#include "value.h"

[[nodiscard]] auto SystemTimeNow(uint32_t num_arguments, Value* values) -> RuntimeErrorOr<Value>;
Expand Down
2 changes: 2 additions & 0 deletions src/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "chunk.h"
#include "error.h"
#include "native_function.h"
#include "value.h"

#include <cstdint>
Expand Down Expand Up @@ -196,6 +197,7 @@ struct ClassObject : public Object {
, class_name(cls_name)
{
}
std::unordered_map<std::string, ClosureObject*> methods;
std::string class_name;
};

Expand Down
13 changes: 13 additions & 0 deletions src/virtual_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,19 @@ auto VirtualMachine::run() -> RuntimeErrorOr<VoidType>
m_value_stack.push_back(rhs);
break;
}
case OP_METHOD: {
auto object = peekStack(0);
LOX_ASSERT(object.IsObject() && object.AsObject().GetType() == ObjectType::CLOSURE);
auto closure_object_ptr = static_cast<ClosureObject*>(object.AsObjectPtr());
object = peekStack(1);
LOX_ASSERT(object.IsObject() && object.AsObject().GetType() == ObjectType::CLASS);
auto class_object_ptr = static_cast<ClassObject*>(object.AsObjectPtr());
object = readConstant();
LOX_ASSERT(object.IsObject() && object.AsObject().GetType() == ObjectType::STRING);
auto method_name = static_cast<StringObject*>(object.AsObjectPtr()); // Will add the to the instance
class_object_ptr->methods[method_name->data] = closure_object_ptr;
break;
}
}
}
}
Expand Down

0 comments on commit c37c05b

Please sign in to comment.