From 8be5386075f93a2b79f31edecb6a5d3527f3d9bf Mon Sep 17 00:00:00 2001 From: Eatswap Date: Mon, 12 Dec 2022 23:20:25 +0800 Subject: [PATCH] add: introduce AST --- AST.cpp | 7 ++ AST.h | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 3 +- context.h | 34 ++++++++ types.h | 17 ++++ value.h | 175 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 AST.cpp create mode 100644 AST.h create mode 100644 context.h create mode 100644 types.h create mode 100644 value.h diff --git a/AST.cpp b/AST.cpp new file mode 100644 index 0000000..502cf2e --- /dev/null +++ b/AST.cpp @@ -0,0 +1,7 @@ +#include + +#include "AST.h" + +namespace DragonLisp { + +} // end of namespace DragonLisp diff --git a/AST.h b/AST.h new file mode 100644 index 0000000..c08f8a6 --- /dev/null +++ b/AST.h @@ -0,0 +1,226 @@ +#ifndef __DRAGON_LISP_AST_H__ +#define __DRAGON_LISP_AST_H__ + +#include +#include + +#include "types.h" +#include "token.h" +#include "context.h" + +namespace DragonLisp { + +enum ASTType { + T_ArrayRefAST, + T_IdentifierAST, + T_FuncDefAST, + T_FuncCallAST, + T_IfAST, + T_LoopAST, + T_UnaryAST, + T_BinaryAST, + T_ListAST, + T_VarOpAST, + T_LValOpAST, +}; + +/// BaseAST - Base class for all AST nodes. +class BaseAST { +public: + virtual ~BaseAST() = default; + + virtual ASTType getType() const = 0; +}; + +class ExprAST : public BaseAST { +public: + virtual std::shared_ptr eval(Context* parent) = 0; +}; + +class LValueAST : public ExprAST { +public: + virtual std::shared_ptr set(Context* parent, std::shared_ptr value) = 0; +}; + +class ArrayRefAST : public LValueAST { +private: + std::string name; + std::shared_ptr index; + +public: + ArrayRefAST(std::string name, std::shared_ptr index) : name(std::move(name)), index(std::move(index)) {} + + ASTType getType() const override final { + return T_ArrayRefAST; + } + + std::shared_ptr eval(Context* parent) override final; + + std::shared_ptr set(Context* parent, std::shared_ptr value) override final; +}; + +class IdentifierAST : public LValueAST { +private: + std::string name; + +public: + explicit IdentifierAST(std::string name) : name(std::move(name)) {} + + ASTType getType() const override final { + return T_IdentifierAST; + } + + std::shared_ptr eval(Context* parent) override final; + + std::shared_ptr set(Context* parent, std::shared_ptr value) override final; +}; + +class FuncDefAST : public BaseAST { +private: + std::string name; + std::vector args; + std::vector> body; + +public: + FuncDefAST(std::string name, std::vector args, std::vector> body) : name(std::move(name)), args(std::move(args)), body(std::move(body)) {} + + std::shared_ptr eval(Context* parent, std::vector> arg); + + inline ASTType getType() const override final { + return T_FuncDefAST; + } +}; + +class FuncCallAST : public ExprAST { +private: + std::string name; + std::vector> args; + +public: + FuncCallAST(std::string name, std::vector> args); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_FuncCallAST; + } +}; + +class IfAST : public ExprAST { +private: + std::shared_ptr cond; + std::shared_ptr then; + std::shared_ptr els; + +public: + IfAST(std::unique_ptr cond, std::unique_ptr then, std::unique_ptr els); + + std::shared_ptr eval(Context* parent) override final { + throw std::runtime_error("You should use IfAST::getResult() instead of IfAST::eval()"); + } + + std::shared_ptr getResult(Context* parent); + + inline ASTType getType() const override final { + return T_IfAST; + } +}; + +class LoopAST : public ExprAST { +private: + std::string loopVar; + std::shared_ptr start; + std::shared_ptr end; + std::shared_ptr body; + +public: + LoopAST(std::string loopVar, std::unique_ptr start, std::unique_ptr end, std::unique_ptr body); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_LoopAST; + } +}; + +class UnaryAST : public ExprAST { +private: + std::shared_ptr expr; + Token op; + +public: + UnaryAST(std::unique_ptr expr, Token op); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_UnaryAST; + } +}; + +class BinaryAST : public ExprAST { +private: + std::shared_ptr lhs; + std::shared_ptr rhs; + Token op; + +public: + BinaryAST(std::unique_ptr lhs, std::unique_ptr rhs, Token op); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_BinaryAST; + } +}; + +class ListAST : public ExprAST { +private: + std::vector> exprs; + Token op; + +public: + ListAST(std::vector> exprs, Token op); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_ListAST; + } +}; + +class VarOpAST : public ExprAST { +private: + std::string name; + std::shared_ptr expr; + Token op; + +public: + VarOpAST(std::string name, std::unique_ptr expr, Token op); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_VarOpAST; + } +}; + +class LValOpAST : public ExprAST { +private: + std::shared_ptr lval; + std::shared_ptr expr; + Token op; + +public: + LValOpAST(std::unique_ptr lval, std::unique_ptr expr, Token op); + + std::shared_ptr eval(Context* parent) override final; + + inline ASTType getType() const override final { + return T_LValOpAST; + } +}; + +} + +#endif // __DRAGON_LISP_AST_H__ diff --git a/Makefile b/Makefile index e4251d5..11389b2 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ COMMONFLAGS ?= -g -Wall CFLAGS ?= $(COMMONFLAGS) -std=c18 CXXFLAGS ?= $(COMMONFLAGS) -std=c++20 -MISCOBJ = main DragonLispDriver +MISCOBJ = main DragonLispDriver AST OBJS = $(addsuffix .o, $(MISCOBJ)) all: compile @@ -49,6 +49,7 @@ compile_debug: lexer parser $(CXX) $(CXXFLAGS) -o $(OUTPUT) \ main.cpp \ DragonLispDriver.cpp \ + AST.cpp \ DragonLisp.tab.cc \ lex.yy.cc diff --git a/context.h b/context.h new file mode 100644 index 0000000..0c0868e --- /dev/null +++ b/context.h @@ -0,0 +1,34 @@ +#ifndef __DRAGON_LISP_CONTEXT_H__ +#define __DRAGON_LISP_CONTEXT_H__ + +#include +#include + +#include "value.h" + +namespace DragonLisp { + +class FuncDefAST; + +class Context { +private: + std::unordered_map> variables; + + Context* parent = nullptr; + + std::unordered_map>* funcs = nullptr; + +public: + explicit Context(Context* p = nullptr) : parent(p) { + this->funcs = p ? p->funcs : new std::unordered_map>; + } + + ~Context() { + if (!this->parent) + delete this->funcs; + } +}; + +} + +#endif // __DRAGON_LISP_CONTEXT_H__ diff --git a/types.h b/types.h new file mode 100644 index 0000000..11cd152 --- /dev/null +++ b/types.h @@ -0,0 +1,17 @@ +#ifndef __DRAGON_LISP_TYPES_H__ +#define __DRAGON_LISP_TYPES_H__ + +namespace DragonLisp { + +enum ValueType { + TYPE_INTEGER, + TYPE_FLOAT, + TYPE_STRING, + TYPE_ARRAY, + TYPE_T, // has no value + TYPE_NIL, // has no value +}; + +} // namespace DragonLisp + +#endif // __DRAGON_LISP_TYPES_H__ diff --git a/value.h b/value.h new file mode 100644 index 0000000..96f5f14 --- /dev/null +++ b/value.h @@ -0,0 +1,175 @@ +#ifndef __DRAGON_LISP_VALUE_H__ +#define __DRAGON_LISP_VALUE_H__ + +#include +#include +#include + +#include "types.h" + +namespace DragonLisp { + +using ValueVariant = std::variant; + +class Value { +public: + virtual bool isArray() const = 0; +}; + +class ArrayValue : public Value { +private: + std::vector values; + + std::size_t size; + +public: + ArrayValue() = delete; + + explicit ArrayValue(std::size_t s) : values(s), size(s) {} + + explicit ArrayValue(std::vector v) : values(std::move(v)), size(this->values.size()) {} + + bool isArray() const override final { + return true; + } + + std::size_t getSize() const { + return this->size; + } + + ValueVariant& operator[](std::size_t i) { + return this->values[i]; + } + + const ValueVariant& operator[](std::size_t i) const { + return this->values[i]; + } + + std::vector& getValues() { + return this->values; + } + + const std::vector& getValues() const { + return this->values; + } +}; + +class SingleValue : public Value { +private: + ValueType type; + + ValueVariant value; + + explicit SingleValue(ValueType t) : type(t), value() {} + +public: + explicit SingleValue(std::int64_t v) : value(v) {} + + explicit SingleValue(double v) : value(v) {} + + explicit SingleValue(std::string v) : value(std::move(v)) {} + + SingleValue() = delete; + + bool isArray() const override final { + return false; + } + + static SingleValue makeT() { + return SingleValue(ValueType::TYPE_T); + } + + static SingleValue makeNil() { + return SingleValue(ValueType::TYPE_NIL); + } + + ValueType getType() const { + return this->type; + } + + bool isT() const { + return this->type == ValueType::TYPE_T; + } + + bool isNil() const { + return this->type == ValueType::TYPE_NIL; + } + + bool isInt() const { + return std::holds_alternative(this->value); + } + + bool isFloat() const { + return std::holds_alternative(this->value); + } + + bool isString() const { + return std::holds_alternative(this->value); + } + + std::int64_t getInt() const { + return std::get(this->value); + } + + double getFloat() const { + return std::get(this->value); + } + + std::string getString() const { + return std::get(this->value); + } + + ValueVariant getValue() const { + return this->value; + } + + void setValue(ValueVariant v) { + this->value = std::move(v); + } +}; + +class _Unused_Variable { +protected: + std::string name; + + std::variant val; + +public: + _Unused_Variable() = delete; + + _Unused_Variable(std::string n, SingleValue v) : name(std::move(n)), val(std::move(v)) {} + + _Unused_Variable(std::string n, ArrayValue v) : name(std::move(n)), val(std::move(v)) {} + + std::string getName() const { + return this->name; + } + + bool isArray() const { + return std::holds_alternative(this->val); + } + + bool isValue() const { + return std::holds_alternative(this->val); + } + + ArrayValue getArray() const { + return std::get(this->val); + } + + SingleValue getValue() const { + return std::get(this->val); + } + + void set(SingleValue v) { + this->val = std::move(v); + } + + void set(ArrayValue v) { + this->val = std::move(v); + } +}; + +} + +#endif // __DRAGON_LISP_VALUE_H__