-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Daedalus): initial AST parser and initial type checker
- Loading branch information
1 parent
80f9654
commit b4de698
Showing
15 changed files
with
3,472 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
Checks: '-*,bugprone-*,cppcoreguidelines-*,concurrency-*,clang-analyzer-*,hicpp-*,misc-*,modernize-*,performance-*,' | ||
'portability-*,readability-*,-modernize-use-trailing-return-type,-cppcoreguidelines-pro-bounds-pointer-arithmetic,' | ||
'-cppcoreguidelines-prefer-member-initializer' | ||
'-cppcoreguidelines-prefer-member-initializer,-*-no-recursion' | ||
WarningsAsErrors: '*' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright © 2023 GothicKit Contributors. | ||
// SPDX-License-Identifier: MIT | ||
#pragma once | ||
#include "zenkit/Error.hh" | ||
#include "zenkit/Library.hh" | ||
#include "zenkit/Stream.hh" | ||
|
||
#include <filesystem> | ||
#include <optional> | ||
#include <string> | ||
#include <unordered_set> | ||
|
||
namespace zenkit::daedalus { | ||
struct CompilationSource; | ||
|
||
struct SourceLocation { | ||
std::shared_ptr<CompilationSource> source; | ||
std::size_t line {0}, column {0}; | ||
|
||
[[nodiscard]] std::string format() const; | ||
}; | ||
|
||
class CompilerError : public Error { | ||
public: | ||
CompilerError(std::string type, SourceLocation loc, std::string message); | ||
|
||
[[nodiscard]] std::string format() const; | ||
|
||
public: | ||
SourceLocation location; | ||
std::string type; | ||
}; | ||
|
||
class SyntaxError : public CompilerError { | ||
public: | ||
SyntaxError(SourceLocation loc, std::string message); | ||
}; | ||
|
||
class TypeError : public CompilerError { | ||
public: | ||
TypeError(SourceLocation loc, std::string message); | ||
}; | ||
|
||
struct CompilationSource { | ||
explicit CompilationSource(std::filesystem::path const& path); | ||
explicit CompilationSource(std::vector<std::byte> source); | ||
explicit CompilationSource(std::unique_ptr<Read> source); | ||
|
||
[[nodiscard]] std::string describe() const; | ||
|
||
std::filesystem::path const path; | ||
std::unique_ptr<Read> read; | ||
}; | ||
|
||
bool operator==(CompilationSource const& a, CompilationSource const& b); | ||
|
||
class Compiler { | ||
public: | ||
ZKAPI void add(std::filesystem::path const& source); | ||
ZKAPI void add_raw(std::string_view source); | ||
ZKAPI void add_src(std::filesystem::path const& source); | ||
|
||
ZKAPI void compile(); | ||
|
||
private: | ||
std::vector<std::shared_ptr<CompilationSource>> _m_sources; | ||
}; | ||
} // namespace zenkit::daedalus |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
// Copyright © 2023 GothicKit Contributors. | ||
// SPDX-License-Identifier: MIT | ||
#pragma once | ||
#include "zenkit/daedalus/SyntaxTree.hh" | ||
|
||
#include <memory> | ||
#include <optional> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <variant> | ||
#include <vector> | ||
|
||
namespace zenkit::daedalus { | ||
enum class SymbolKind { | ||
VAR, | ||
CONST, | ||
CLASS, | ||
PROTOTYPE, | ||
INSTANCE, | ||
FUNC, | ||
EXTERN, | ||
}; | ||
|
||
enum class PrimitiveType { | ||
VOID = 0, | ||
INT, | ||
INT_ARRAY, | ||
FLOAT, | ||
FLOAT_ARRAY, | ||
STRING, | ||
STRING_ARRAY, | ||
FUNC, | ||
FUNC_ARRAY, | ||
}; | ||
|
||
class ClassSymbol; | ||
|
||
class Type { | ||
public: | ||
explicit Type(PrimitiveType t); | ||
explicit Type(ClassSymbol* t); | ||
|
||
[[nodiscard]] bool is_convertible(Type other) const noexcept; | ||
|
||
[[nodiscard]] bool is_primitive() const noexcept; | ||
[[nodiscard]] bool is_void() const noexcept; | ||
[[nodiscard]] bool is_array() const noexcept; | ||
[[nodiscard]] Type to_array() const noexcept; | ||
[[nodiscard]] Type to_elemental() const noexcept; | ||
|
||
[[nodiscard]] PrimitiveType get_primitive_type() const; | ||
[[nodiscard]] ClassSymbol* get_complex_type() const; | ||
|
||
[[nodiscard]] std::string const& describe() const; | ||
|
||
static Type VOID; | ||
static Type INT; | ||
static Type FLOAT; | ||
static Type STRING; | ||
static Type FUNC; | ||
|
||
private: | ||
friend bool operator==(Type a, Type b) noexcept; | ||
|
||
std::variant<PrimitiveType, ClassSymbol*> _m_type; | ||
}; | ||
|
||
bool operator==(Type a, Type b) noexcept; | ||
bool operator!=(Type a, Type b) noexcept; | ||
|
||
class Symbol { | ||
public: | ||
Symbol(SymbolKind type, std::string name); | ||
|
||
Symbol(Symbol&&) = default; | ||
virtual ~Symbol() noexcept = default; | ||
|
||
[[nodiscard]] SymbolKind get_kind() const noexcept; | ||
[[nodiscard]] std::string const& get_name() const noexcept; | ||
|
||
protected: | ||
SymbolKind _m_type; | ||
std::string const _m_name; | ||
}; | ||
|
||
class VarSymbol : public Symbol { | ||
public: | ||
VarSymbol(std::string name, Type type); | ||
VarSymbol(std::string name, Type type, AstVariable ast); | ||
|
||
[[nodiscard]] Type get_type() const; | ||
|
||
void set_size(int size); | ||
[[nodiscard]] int get_size() const; | ||
|
||
[[nodiscard]] inline std::optional<AstVariable*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
Type _m_value_type; | ||
int _m_size = 0; | ||
std::optional<AstVariable> _m_ast; | ||
}; | ||
|
||
class ConstSymbol : public Symbol { | ||
public: | ||
ConstSymbol(std::string name, Type type); | ||
ConstSymbol(std::string name, Type type, AstConstant ast); | ||
|
||
[[nodiscard]] Type get_type() const; | ||
|
||
void set_size(int size); | ||
[[nodiscard]] int get_size() const; | ||
|
||
[[nodiscard]] inline std::optional<AstConstant*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
Type _m_value_type; | ||
int _m_size = 0; | ||
std::optional<AstConstant> _m_ast; | ||
}; | ||
|
||
class Scope { | ||
public: | ||
std::vector<VarSymbol>& get_local_vars(); | ||
|
||
VarSymbol* add_local_var(std::string name, Type type, AstVariable ast); | ||
|
||
private: | ||
// TODO: For extra fine-grained control, properly scope these. | ||
std::vector<VarSymbol> _m_local_vars; | ||
}; | ||
|
||
class ClassSymbol : public Symbol { | ||
public: | ||
explicit ClassSymbol(std::string name); | ||
ClassSymbol(std::string name, AstClass ast); | ||
|
||
VarSymbol* get_member(std::string const& name); | ||
VarSymbol* get_member(AstIdentifier const& name); | ||
|
||
void add_member(std::string name, Type type); | ||
void add_member(std::string name, Type type, AstVariable ast); | ||
|
||
std::vector<VarSymbol>& get_members(); | ||
|
||
[[nodiscard]] inline std::optional<AstClass*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
std::vector<VarSymbol> _m_members; | ||
std::optional<AstClass> _m_ast; | ||
}; | ||
|
||
class PrototypeSymbol : public Symbol { | ||
public: | ||
PrototypeSymbol(std::string name, ClassSymbol* base); | ||
PrototypeSymbol(std::string name, ClassSymbol* base, AstPrototype ast); | ||
|
||
[[nodiscard]] ClassSymbol* get_base() const noexcept; | ||
|
||
Scope& get_scope(); | ||
|
||
[[nodiscard]] inline std::optional<AstPrototype*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
ClassSymbol* _m_base; | ||
std::optional<AstPrototype> _m_ast; | ||
Scope _m_scope; | ||
}; | ||
|
||
class InstanceSymbol : public Symbol { | ||
public: | ||
InstanceSymbol(std::string name, Symbol* base); | ||
InstanceSymbol(std::string name, Symbol* base, AstInstance ast); | ||
|
||
[[nodiscard]] Symbol* get_base() const noexcept; | ||
[[nodiscard]] ClassSymbol* get_base_class() const noexcept; | ||
|
||
Scope& get_scope(); | ||
|
||
[[nodiscard]] inline std::optional<AstInstance*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
Symbol* _m_base; | ||
std::optional<AstInstance> _m_ast; | ||
Scope _m_scope; | ||
}; | ||
|
||
class FunctionSymbol : public Symbol { | ||
public: | ||
FunctionSymbol(std::string name, Type rtype); | ||
FunctionSymbol(std::string name, Type rtype, AstFunction ast); | ||
|
||
[[nodiscard]] Type get_return_type() const; | ||
|
||
VarSymbol* get_argument(std::string const& name); | ||
VarSymbol* get_argument(AstIdentifier const& name); | ||
|
||
void add_argument(std::string name, Type type); | ||
void add_argument(std::string name, Type type, AstVariable ast); | ||
|
||
std::vector<VarSymbol>& get_arguments(); | ||
|
||
Scope& get_scope(); | ||
|
||
[[nodiscard]] inline std::optional<AstFunction*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
Type _m_return_type; | ||
std::vector<VarSymbol> _m_args; | ||
std::optional<AstFunction> _m_ast; | ||
Scope _m_scope; | ||
}; | ||
|
||
class ExternSymbol : public Symbol { | ||
public: | ||
ExternSymbol(std::string name, Type rtype); | ||
ExternSymbol(std::string name, Type rtype, AstExternal ast); | ||
|
||
[[nodiscard]] Type get_return_type() const; | ||
|
||
VarSymbol* get_argument(std::string const& name); | ||
VarSymbol* get_argument(AstIdentifier const& name); | ||
|
||
void add_argument(std::string name, Type type); | ||
void add_argument(std::string name, Type type, AstVariable ast); | ||
|
||
std::vector<VarSymbol>& get_arguments(); | ||
|
||
[[nodiscard]] inline std::optional<AstExternal*> get_ast() noexcept { | ||
if (_m_ast) return &*_m_ast; | ||
return std::nullopt; | ||
} | ||
|
||
private: | ||
Type _m_return_type; | ||
std::vector<VarSymbol> _m_args; | ||
std::optional<AstExternal> _m_ast; | ||
}; | ||
} // namespace zenkit::daedalus |
Oops, something went wrong.