diff --git a/Makefile b/Makefile index f9ae111..6e47f25 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SRC = $(wildcard ${DIR_SRC}/*.cc) TMP = $(wildcard $(DIR_TMP)/*.o) all: - ${CC} -std=c++20 -c $(foreach i, $(SRC), $(i)) + ${CC} -std=c++20 -c -Os $(foreach i, $(SRC), $(i)) install: $(shell mkdir ${DIR_TMP}) diff --git a/src/ast.h b/src/ast.h index 8c3e12f..d339f6f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -18,136 +18,10 @@ #include #include "token.h" +#include "type.h" // abstract syntax tree namespace ast { -// types for drift -enum TypeKind { - T_INT, // int - T_FLOAT, // float - T_STR, // str - T_CHAR, // char - T_BOOL, // bool - T_ARRAY, // [] - T_MAP, // - T_TUPLE, // (T) - T_USER, // user -}; - -// basic type for drift -// -#define S_INT "int" // 1 -#define S_FLOAT "float" // 2 -#define S_STR "str" // 3 -#define S_CHAR "char" // 4 -#define S_BOOL "bool" // 5 - -// TYPE -class Type { -public: - // stringer - virtual std::string stringer() = 0; - // kind of basic type - virtual TypeKind kind() = 0; -}; - -// -class Int : public Type { -public: - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_INT; } -}; - -// float -class Float : public Type { -public: - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_FLOAT; } -}; - -// str -class Str : public Type { -public: - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_STR; } -}; - -// char -class Char : public Type { -public: - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_CHAR; } -}; - -// bool -class Bool : public Type { -public: - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_BOOL; } -}; - -// array (not keyword, for compiler analysis) -// [] -class Array : public Type { -public: - Type *T; // type for elements - - explicit Array(Type *T) : T(T) {} - - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_ARRAY; } -}; - -// map (not keyword, for compiler analysis) -// -class Map : public Type { -public: - Type *T1; // K - Type *T2; // V - - explicit Map(Type *T1, Type *T2) : T1(T1), T2(T2) {} - - std::string stringer() override { - return ""; - } - - TypeKind kind() override { return T_MAP; } -}; - -// tuple (not keyword, for compiler analysis) -// (type) -class Tuple : public Type { -public: - Type *T; // type for elements - - explicit Tuple(Type *T) : T(T) {} - - std::string stringer() override { return ""; } - - TypeKind kind() override { return T_TUPLE; } -}; - -// user definition type -// `type` -class User : public Type { -public: - token::Token name; - - explicit User(token::Token name) { this->name = std::move(name); } - - std::string stringer() override { - return ""; - } - - TypeKind kind() override { return T_USER; } -}; - // ast types enum Kind { // expression @@ -166,23 +40,24 @@ enum Kind { EXPR_INDEX, // EXPR[EXPR] EXPR_NEW, // statement - STMT_EXPR, // EXPR - STMT_VAR, // VAR - STMT_BLOCK, // BLOCK - STMT_IF, // IF - STMT_FOR, // FOR - STMT_DO, // DO - STMT_OUT, // OUT - STMT_TIN, // TIN - STMT_FUNC, // FUNC - STMT_WHOLE, // CLASS | ENUM - STMT_AND, // AND - STMT_MOD, // MOD - STMT_USE, // USE - STMT_RET, // RET - STMT_ENUM, // ENUM - STMT_INHERIT, // <- + .. - STMT_INTERFACE // INTERFACE + STMT_EXPR, // EXPR + STMT_VAR, // VAR + STMT_BLOCK, // BLOCK + STMT_IF, // IF + STMT_FOR, // FOR + STMT_DO, // DO + STMT_OUT, // OUT + STMT_TIN, // TIN + STMT_FUNC, // FUNC + STMT_WHOLE, // CLASS | ENUM + STMT_AND, // AND + STMT_MOD, // MOD + STMT_USE, // USE + STMT_RET, // RET + STMT_ENUM, // ENUM + STMT_INHERIT, // <- + .. + STMT_INTERFACE, // INTERFACE + STMT_DEL // DEL }; // K1: V1 | K1 + K2: V2 @@ -528,26 +403,20 @@ class VarStmt : public Stmt { // default is not init Expr *expr = nullptr; - bool local = false; - // has expr - explicit VarStmt(token::Token name, Type *T, Expr *e, bool local) - : T(T), expr(e) { + explicit VarStmt(token::Token name, Type *T, Expr *e) : T(T), expr(e) { this->name = std::move(name); - this->local = local; } // not init expr - explicit VarStmt(token::Token name, Type *T, bool local) : T(T) { + explicit VarStmt(token::Token name, Type *T) : T(T) { this->name = std::move(name); - this->local = local; } std::string stringer() override { std::stringstream str; - str << ""; @@ -970,6 +839,20 @@ class EnumStmt : public Stmt { Kind kind() override { return STMT_ENUM; } }; + +// del +class DelStmt : public Stmt { +public: + token::Token name; + + explicit DelStmt(token::Token n) : name(std::move(n)) {} + + std::string stringer() override { + return ""; + } + + Kind kind() override { return STMT_DEL; } +}; }; // namespace ast #endif \ No newline at end of file diff --git a/src/compiler.cc b/src/compiler.cc index 71715f4..b9887e5 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -23,7 +23,7 @@ void Compiler::compile() { while (this->position < this->statements.size()) { this->line = this->lineno.at(this->position); - + this->stmt(look()); // START this->position++; } @@ -61,7 +61,7 @@ void Compiler::emitName(std::string v) { } // push names type to entity -void Compiler::emitType(ast::Type *t) { +void Compiler::emitType(Type *t) { this->now->types.push_back(t); this->emitOffset(this->itf++); } @@ -607,6 +607,11 @@ void Compiler::stmt(ast::Stmt *stmt) { this->emitConstant(obj); // push to constant object } break; // + case ast::STMT_DEL: { + this->emitCode(byte::DEL); + this->emitName(static_cast(stmt)->name.literal); // name + } break; + // default: break; } diff --git a/src/compiler.h b/src/compiler.h index e22fd91..121af9c 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -18,6 +18,7 @@ #include #include "ast.h" +#include "type.h" #include "entity.h" #include "object.h" #include "opcode.h" @@ -43,7 +44,7 @@ class Compiler { void emitOffset(int); // push offset to entity void emitConstant(object::Object *); // push constant to entity void emitName(std::string); // push name to entity - void emitType(ast::Type *); // push names type to entity + void emitType(Type *); // push names type to entity void emitJumpOffset(int); diff --git a/src/entity.h b/src/entity.h index c4fa305..530d4f6 100644 --- a/src/entity.h +++ b/src/entity.h @@ -19,6 +19,7 @@ #include #include "ast.h" +#include "type.h" #include "object.h" #include "opcode.h" @@ -33,7 +34,7 @@ struct Entity { std::vector offsets; // offset of bytecode std::vector constants; // constant std::vector names; // names - std::vector types; // type of variables + std::vector types; // type of variables std::vector lineno; // line no of each bytecode @@ -89,6 +90,7 @@ struct Entity { case byte::GET: case byte::SET: case byte::MOD: + case byte::DEL: case byte::USE: { printf("%10d %5d: %s %12d '%s'\n", ip, lineno.at(ip), byte::codeString[codes.at(ip)].c_str(), offsets.at(op++), diff --git a/src/lexer.cc b/src/lexer.cc index c4a6e8f..16cdf1b 100644 --- a/src/lexer.cc +++ b/src/lexer.cc @@ -332,7 +332,6 @@ void Lexer::lexSymbol() { case '_': tok.kind = token::UNDERLINE; break; - break; default: error(exp::UNKNOWN_SYMBOL, "unknown symbol: " + std::to_string(now())); diff --git a/src/object.h b/src/object.h index 36bc530..c6f0315 100644 --- a/src/object.h +++ b/src/object.h @@ -16,6 +16,7 @@ #define DRIFT_OBJECT_H #include "ast.h" +#include "type.h" struct Entity; struct Frame; @@ -276,7 +277,7 @@ class Func : public Object { std::string name; // function name ast::FuncArg arguments; // function args - ast::Type *ret; // function return + Type *ret; // function return Entity *entity; // function entity @@ -296,7 +297,7 @@ class Whole : public Object { Entity *entity; // whole entity // interface definition - std::vector> interface; + std::vector> interface; // inherit definition std::vector inherit; diff --git a/src/opcode.h b/src/opcode.h index d917f77..f2eecc9 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -20,7 +20,7 @@ // bytecode namespace byte { // total number of bytecodes -constexpr int len = 40; +constexpr int len = 41; // bytecode type enum Code { CONST, // CONST @@ -35,9 +35,11 @@ enum Code { ORIG, // ORIG NAME, // NAME NEW, // NEW - FUNC, // FUNC - WHOLE, // WHOLE - ENUM, // ENUM + DEL, // DEL + + FUNC, // FUNC + WHOLE, // WHOLE + ENUM, // ENUM MOD, // MOD USE, // USE @@ -75,11 +77,12 @@ enum Code { // return a string of bytecode static std::string codeString[len] = { - "CONST", "ASSIGN", "STORE", "LOAD", "INDEX", "REPLACE", "GET", "SET", - "CALL", "ORIG", "NAME", "NEW", "FUNC", "WHOLE", "ENUM", "MOD", - "USE", "B_ARR", "B_TUP", "B_MAP", "ADD", "SUB", "MUL", "DIV", - "SUR", "GR", "LE", "GR_E", "LE_E", "E_E", "N_E", "AND", - "OR", "BANG", "NOT", "JUMP", "F_JUMP", "T_JUMP", "RET_N", "RET", + "CONST", "ASSIGN", "STORE", "LOAD", "INDEX", "REPLACE", "GET", + "SET", "CALL", "ORIG", "NAME", "NEW", "DEL", "FUNC", + "WHOLE", "ENUM", "MOD", "USE", "B_ARR", "B_TUP", "B_MAP", + "ADD", "SUB", "MUL", "DIV", "SUR", "GR", "LE", + "GR_E", "LE_E", "E_E", "N_E", "AND", "OR", "BANG", + "NOT", "JUMP", "F_JUMP", "T_JUMP", "RET_N", "RET", }; }; // namespace byte diff --git a/src/parser.cc b/src/parser.cc index 18fa012..98428f4 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -374,29 +374,25 @@ ast::Expr *Parser::primary() { ast::Stmt *Parser::stmt() { switch (this->look().kind) { // definition statement - case token::DEF: - case token::LET: { + case token::DEF: { this->position++; - token::Kind k = previous().kind; + // TODO: local + // bool local = look(token::MUL); // local - // let and name decoration - if (look().kind != token::IDENT && k == token::LET) { - error(exp::UNEXPECTED, "let name decoration can only be an ident"); - } // variable if (look(token::IDENT) && look().kind == token::COLON) { token::Token name = previous(); this->position++; // skip colon symbol - ast::Type *T = this->type(); + Type *T = this->type(); // value of variable if (look(token::EQ)) // there is an initial value - return new ast::VarStmt(name, T, this->expr(), k == token::LET); + return new ast::VarStmt(name, T, this->expr()); else - return new ast::VarStmt(name, T, k == token::LET); + return new ast::VarStmt(name, T); } // function or interface else if (look(token::L_PAREN)) { @@ -407,7 +403,7 @@ ast::Stmt *Parser::stmt() { // name token::Token name; // return - ast::Type *ret = nullptr; + Type *ret = nullptr; // cache multiple parameters std::vector temp; @@ -460,7 +456,7 @@ ast::Stmt *Parser::stmt() { funcArgs.insert(std::make_pair(K, this->type())); } else { // multip - ast::Type *T = this->type(); + Type *T = this->type(); for (auto i : temp) { funcArgs.insert(std::make_pair(i, T)); @@ -485,6 +481,12 @@ ast::Stmt *Parser::stmt() { // current parsing interface statement interfaceStmt = true; } + // anonymouse function + else if (look(token::R_ARROW)) { + return new ast::FuncStmt( + funcArgs, token::Token{.kind = token::EFF, .literal = "anonymouse"}, + this->type(), this->block(token::END)); + } // error else { error(exp::UNEXPECTED, @@ -632,6 +634,15 @@ ast::Stmt *Parser::stmt() { return new ast::InheritStmt(names); } break; + // del + case token::DEL: { + this->position++; + // + if (!look(token::IDENT)) { + error(exp::UNEXPECTED, "del name must be an identifier"); + } + return new ast::DelStmt(previous()); + } break; // default: // expression statement @@ -678,7 +689,7 @@ inline void Parser::error(exp::Kind kind, std::string message) { } // type analysis -ast::Type *Parser::type(bool previous) { +Type *Parser::type(bool previous) { token::Token now = *this->look(previous); // type if (now.kind == token::IDENT) { @@ -686,57 +697,83 @@ ast::Type *Parser::type(bool previous) { this->position++; // T1 if (now.literal == S_INT) - return new ast::Int(); + return new Int(); // T2 if (now.literal == S_FLOAT) - return new ast::Float(); + return new Float(); // T3 if (now.literal == S_STR) - return new ast::Str; + return new Str; // T4 if (now.literal == S_CHAR) - return new ast::Char(); + return new Char(); // T5 if (now.literal == S_BOOL) - return new ast::Bool; + return new Bool; // user define type - return new ast::User(now); + return new User(now); } // T6 if (now.kind == token::L_BRACKET) { this->position++; // skip left [ symbol + int count = -1; + + // set default original value + if (look(token::NUM)) { + count = atoi(this->previous().literal.c_str()); + } + if (!look(token::R_BRACKET)) { error(exp::UNEXPECTED, "expect ']' after left square bracket"); } - return new ast::Array(this->type()); + return new Array(this->type(), count); } // T7 if (now.kind == token::LESS) { this->position++; // skip left < symbol // key - ast::Type *T1 = this->type(); + Type *T1 = this->type(); if (!look(token::COMMA)) { error(exp::UNEXPECTED, "expect ',' after key of map"); } - ast::Type *T2 = this->type(); + Type *T2 = this->type(); if (!look(token::GREATER)) { error(exp::UNEXPECTED, "expect '>' after value of map"); } - return new ast::Map(T1, T2); + return new Map(T1, T2); } // T8 if (now.kind == token::L_PAREN) { this->position++; // skip left ( symbol - ast::Type *T = this->type(); + Type *T = this->type(); if (!look(token::R_PAREN)) { error(exp::UNEXPECTED, "expect ')' after tuple define"); } - return new ast::Tuple(T); + return new Tuple(T); + } + // T9 + if (now.kind == token::OR) { + this->position++; // skip left | symbol + + std::vector arguments; // function arguments + Type *ret = nullptr; // function return + + while (!look(token::OR)) { + arguments.push_back(this->type()); + + if (look(token::COMMA)) { + continue; + } + } + if (look(token::R_ARROW)) { + ret = this->type(); + } + return new Func(arguments, ret); } error(exp::INVALID_SYNTAX, "invalid type"); // diff --git a/src/parser.h b/src/parser.h index ef06a17..a13c103 100644 --- a/src/parser.h +++ b/src/parser.h @@ -20,6 +20,7 @@ #include "ast.h" #include "exception.h" #include "state.h" +#include "type.h" // parser structure class Parser { @@ -69,7 +70,7 @@ class Parser { ast::BlockStmt *block(token::Kind x, token::Kind y = token::EFF, token::Kind z = token::EFF); - ast::Type *type(bool previous = false); // parse types + Type *type(bool previous = false); // parse types // throw an exception inline void error(exp::Kind, std::string); diff --git a/src/token.cc b/src/token.cc index ce775b9..7aa728d 100644 --- a/src/token.cc +++ b/src/token.cc @@ -7,17 +7,17 @@ void initializeKeyword(std::map *map) { map->insert(std::make_pair("use", USE)); // 1 map->insert(std::make_pair("def", DEF)); // 2 map->insert(std::make_pair("ret", RET)); // 3 - map->insert(std::make_pair("let", LET)); // 4 - map->insert(std::make_pair("end", END)); // 5 - map->insert(std::make_pair("if", IF)); // 6 - map->insert(std::make_pair("ef", EF)); // 7 - map->insert(std::make_pair("nf", NF)); // 8 - map->insert(std::make_pair("for", FOR)); // 9 - map->insert(std::make_pair("do", DO)); // 10 - map->insert(std::make_pair("out", OUT)); // 11 - map->insert(std::make_pair("tin", TIN)); // 12 - map->insert(std::make_pair("new", NEW)); // 13 - map->insert(std::make_pair("mod", MOD)); // 14 + map->insert(std::make_pair("end", END)); // 4 + map->insert(std::make_pair("if", IF)); // 5 + map->insert(std::make_pair("ef", EF)); // 6 + map->insert(std::make_pair("nf", NF)); // 7 + map->insert(std::make_pair("for", FOR)); // 8 + map->insert(std::make_pair("do", DO)); // 9 + map->insert(std::make_pair("out", OUT)); // 10 + map->insert(std::make_pair("tin", TIN)); // 11 + map->insert(std::make_pair("new", NEW)); // 12 + map->insert(std::make_pair("mod", MOD)); // 13 + map->insert(std::make_pair("del", DEL)); // 14 } token::Kind getKeyword(std::map m, diff --git a/src/token.h b/src/token.h index fdd4321..767d9ad 100644 --- a/src/token.h +++ b/src/token.h @@ -79,17 +79,17 @@ enum Kind { USE, // 1 DEF, // 2 RET, // 3 - LET, // 4 - END, // 5 - IF, // 6 - EF, // 7 - NF, // 8 - FOR, // 9 - DO, // 10 - OUT, // 11 - TIN, // 12 - NEW, // 13 - MOD // 14 + END, // 4 + IF, // 5 + EF, // 6 + NF, // 7 + FOR, // 8 + DO, // 9 + OUT, // 10 + TIN, // 11 + NEW, // 12 + MOD, // 13 + DEL, // 14 }; // returns a string of each type @@ -108,10 +108,10 @@ static std::string kindString[len] = { "R_BRACE", "L_PAREN", "R_PAREN", "L_BRACKET", "R_BRACKET", "UNDERLINE", "EFF", "USE", "DEF", - "RET", "LET", "END", - "IF", "EF", "NF", - "FOR", "DO", "OUT", - "TIN", "NEW", "MOD", + "RET", "END", "IF", + "EF", "NF", "FOR", + "DO", "OUT", "TIN", + "NEW", "MOD", "DEL", }; // token structure diff --git a/src/type.h b/src/type.h index ce626e4..0a24439 100644 --- a/src/type.h +++ b/src/type.h @@ -29,6 +29,7 @@ enum TypeKind { T_ARRAY, // [] T_MAP, // T_TUPLE, // (T) + T_FUNC, // |A| -> R T_USER, // user }; @@ -95,9 +96,17 @@ class Array : public Type { public: Type *T; // type for elements - explicit Array(Type *T) : T(T) {} + int count; // defaule built original value - std::string stringer() override { return ""; } + explicit Array(Type *T, int count) : T(T), count(count) {} + + std::string stringer() override { + if (count != -1) { + return ""; + } + return ""; + } TypeKind kind() override { return T_ARRAY; } }; @@ -112,7 +121,7 @@ class Map : public Type { explicit Map(Type *T1, Type *T2) : T1(T1), T2(T2) {} std::string stringer() override { - return ""; + return ""; } TypeKind kind() override { return T_MAP; } @@ -126,11 +135,31 @@ class Tuple : public Type { explicit Tuple(Type *T) : T(T) {} - std::string stringer() override { return ""; } + std::string stringer() override { return ""; } TypeKind kind() override { return T_TUPLE; } }; +// function +class Func : public Type { +public: + std::vector arguments; // function arguments + Type *ret; // function return + + explicit Func(std::vector arguments, Type *ret) + : arguments(arguments), ret(ret) {} + + std::string stringer() override { + if (ret == nullptr) { + return ""; + } + return ""; + } + + TypeKind kind() override { return T_FUNC; } +}; + // user definition type // `type` class User : public Type { @@ -140,7 +169,7 @@ class User : public Type { explicit User(token::Token name) { this->name = std::move(name); } std::string stringer() override { - return ""; + return ""; } TypeKind kind() override { return T_USER; } diff --git a/src/vm.cc b/src/vm.cc index 6799a98..6c641ef 100644 --- a/src/vm.cc +++ b/src/vm.cc @@ -26,8 +26,8 @@ void vm::pushData(object::Object *obj) { top()->data.push(obj); } // pop the top of data stack object::Object *vm::popData() { return top()->data.pop(); } -#define PUSH(obj) this->pushData(obj) -#define POP this->popData +#define PUSH(obj) this->pushData(obj) // PUSH +#define POP this->popData // POP // emit new name of table to the current frame void vm::emitTable(std::string name, object::Object *obj) { @@ -74,7 +74,7 @@ object::Object *vm::retConstant() { } // first to end -ast::Type *vm::retType() { return top()->entity->types.at(GET_OFFSET(op)); } +Type *vm::retType() { return top()->entity->types.at(GET_OFFSET(op)); } // first to end std::string vm::retName() { return top()->entity->names.at(GET_OFFSET(op)); } @@ -92,11 +92,15 @@ void vm::error(std::string message) { } // are the comparison types the same -void vm::typeChecker(ast::Type *x, object::Object *y) { +void vm::typeChecker(Type *x, object::Object *y) { switch (x->kind()) { // array - case ast::T_ARRAY: { - ast::Array *T = static_cast(x); + case T_ARRAY: { + Array *T = static_cast(x); + + if (y->kind() != object::ARRAY) + error("type error not found array"); + object::Array *arr = static_cast(y); for (auto i : arr->elements) @@ -104,8 +108,12 @@ void vm::typeChecker(ast::Type *x, object::Object *y) { break; } // tuple - case ast::T_TUPLE: { - ast::Tuple *T = static_cast(x); + case T_TUPLE: { + Tuple *T = static_cast(x); + + if (y->kind() != object::TUPLE) + error("type error not found tuple"); + object::Tuple *tup = static_cast(y); for (auto i : tup->elements) @@ -113,8 +121,12 @@ void vm::typeChecker(ast::Type *x, object::Object *y) { break; } // map - case ast::T_MAP: { - ast::Map *T = static_cast(x); + case T_MAP: { + Map *T = static_cast(x); + + if (y->kind() != object::MAP) + error("type error not found map"); + object::Map *map = static_cast(y); for (auto &i : map->elements) { @@ -123,26 +135,66 @@ void vm::typeChecker(ast::Type *x, object::Object *y) { } break; } + // func + case T_FUNC: { + Func *T = static_cast(x); + + if (y->kind() != object::FUNC) + error("type error not found function"); + + object::Func *f = static_cast(y); + + if (f->arguments.size() != T->arguments.size()) + error("wrong number of parameters"); + + if (f->ret != nullptr && T->ret != nullptr) + if (f->ret->kind() != T->ret->kind()) + error("wrong return type"); + + std::map::iterator iter = + f->arguments.begin(); // ITER + + for (int i = 0; i < T->arguments.size(); i += 1, iter++) { + // CATCH + if (T->arguments.at(i)->kind() != iter->second->kind()) + error("wrong argument type with function"); + } + break; + } // other default: { // base if ( // int - (x->kind() == ast::T_INT && y->kind() != object::INT) || + (x->kind() == T_INT && y->kind() != object::INT) || // float - (x->kind() == ast::T_FLOAT && y->kind() != object::FLOAT) || + (x->kind() == T_FLOAT && y->kind() != object::FLOAT) || // str - (x->kind() == ast::T_STR && y->kind() != object::STR) || + (x->kind() == T_STR && y->kind() != object::STR) || // char - (x->kind() == ast::T_CHAR && y->kind() != object::CHAR) || + (x->kind() == T_CHAR && y->kind() != object::CHAR) || // bool - (x->kind() == ast::T_BOOL && y->kind() != object::INT)) { + (x->kind() == T_BOOL && y->kind() != object::INT)) { + + // type transfer + // + // int -> float + // + if (x->kind() == T_FLOAT && y->kind() == object::INT) { + *y = object::Float(static_cast(y)->value); + return; + } + // float -> int + if (x->kind() == T_INT && y->kind() == object::FLOAT) { + *y = object::Int(static_cast(y)->value); + return; + } error("type error, require: " + x->stringer() + ", found: " + y->rawStringer()); } else { // user - if (x->kind() == ast::T_USER) { - std::string name = static_cast(x)->name.literal; + if (x->kind() == T_USER) { + std::string name = static_cast(x)->name.literal; switch (y->kind()) { // function @@ -196,24 +248,24 @@ bool vm::objValueEquation(object::Object *x, object::Object *y) { } // generate default value -object::Object *vm::setOriginalValue(ast::Type *t) { +object::Object *vm::setOriginalValue(Type *t) { switch (t->kind()) { - case ast::T_INT: + case T_INT: return new object::Int(0); - case ast::T_FLOAT: + case T_FLOAT: return new object::Float(0.0); - case ast::T_STR: + case T_STR: return new object::Str(""); - case ast::T_CHAR: + case T_CHAR: return new object::Char(0); - case ast::T_BOOL: + case T_BOOL: return new object::Int(0); // default conversion - case ast::T_ARRAY: + case T_ARRAY: return new object::Array(); - case ast::T_TUPLE: + case T_TUPLE: return new object::Tuple(); - case ast::T_MAP: + case T_MAP: return new object::Map(); default: @@ -335,7 +387,6 @@ void vm::newWhole(std::string name, int count, bool inner) { // INHERIT if (!w->inherit.empty()) { for (auto i : w->inherit) { - object::Object *obj = this->lookUp(i); if (obj == nullptr) @@ -344,71 +395,61 @@ void vm::newWhole(std::string name, int count, bool inner) { error("only whole object can be inherited"); // INTERFACE - object::Whole *it = static_cast(obj); - - for (std::tuple i : - it->interface) { - // std::cout << std::get<0>(i) << std::endl; + this->checkInterface(static_cast(obj), w); + } + } - // TO TABLE SYMBOL - std::map::iterator iter; + w->newOut = true; // TO NEW - // std::cout << w->f->tb.symbols.size() << std::endl; + PUSH(w); // PUSH + this->op = inner ? t : ++t; // NEXT +} - for (iter = w->f->tb.symbols.begin(); iter != w->f->tb.symbols.end(); - iter++) { - // NAME - if (iter->first == std::get<0>(i)) { - // std::cout << "NAME: " << iter->first << - // std::endl; - // - if (iter->second->kind() != object::FUNC) { - error("subclass inheritance is not " - "function"); - } +// to check interface of whole +void vm::checkInterface(object::Whole *it, object::Whole *se) { + for (std::tuple i : it->interface) { + // TO TABLE SYMBOL + std::map::iterator iter; + + for (iter = se->f->tb.symbols.begin(); iter != se->f->tb.symbols.end(); + iter++) { + // NAME + if (iter->first == std::get<0>(i)) { + // std::cout << "NAME: " << iter->first << + // std::endl; + // + if (iter->second->kind() != object::FUNC) + error("subclass inheritance is not function"); - object::Func *f = static_cast(iter->second); + object::Func *f = static_cast(iter->second); - // RETURN - if (f->ret->kind() != std::get<2>(i)->kind()) { - error("bad return type for subclass " - "inheritance"); - } - // ARGUMENT - if (std::get<1>(i).size() != f->arguments.size()) { - error("inconsistent arguments for " - "subclass inheritance"); - } - // TYPE - auto x = std::get<1>(i).begin(); // T - auto y = f->arguments.begin(); // K, T - - while (y != f->arguments.end()) { - // - if ((*x)->kind() != y->second->kind()) { - error("subclass inheritance " - "parameter " + - y->second->stringer() + " no " + (*x)->stringer()); - } - *x++; // NEXT - *y++; // NEXT - } - break; - }; - } - - // NOT FOUND - if (iter == w->f->tb.symbols.end()) { - error("not inherited method '" + std::get<0>(i) + "' of subclass"); + // RETURN + if (f->ret->kind() != std::get<2>(i)->kind()) + error("bad return type for subclass inheritance"); + // ARGUMENT + if (std::get<1>(i).size() != f->arguments.size()) + error("inconsistent arguments for subclass inheritance"); + + // TYPE + auto x = std::get<1>(i).begin(); // T + auto y = f->arguments.begin(); // K, T + + while (y != f->arguments.end()) { + // + if ((*x)->kind() != y->second->kind()) + error("subclass inheritance parameter " + y->second->stringer() + + " no " + (*x)->stringer()); + *x++; // NEXT + *y++; // NEXT } - } + break; + }; } - } - w->newOut = true; // TO NEW - - PUSH(w); // PUSH - this->op = ++t; // NEXT + // NOT FOUND + if (iter == se->f->tb.symbols.end()) + error("not inherited method '" + std::get<0>(i) + "' of subclass"); + } } void vm::evaluate() { // EVALUATE @@ -1175,8 +1216,10 @@ void vm::evaluate() { // EVALUATE object::Object *obj; std::string name = this->retName(); // TO NAME + // std::cout << "STORE: " << name << std::endl; + this->op++; - ast::Type *type = this->retType(); // TO TYPE + Type *type = this->retType(); // TO TYPE if (top()->entity->codes.at(ip - 1) == byte::ORIG) { // ORIGINAL obj = this->setOriginalValue(type); // VALUE @@ -1184,13 +1227,24 @@ void vm::evaluate() { // EVALUATE obj = POP(); // OBJECT } - if (type->kind() == ast::T_BOOL) { + if (type->kind() == T_BOOL) { // transfrom integer to boolean obj = new object::Bool(static_cast(obj)->value); } else { this->typeChecker(type, obj); // TYPE CHECKER } + // set default original elements + if (type->kind() == T_ARRAY) { + Array *T = static_cast(type); + object::Array *a = static_cast(obj); + + for (int i = a->elements.size(); i < T->count; i += 1) { + a->elements.insert(a->elements.begin() + i, + this->setOriginalValue(T->T)); // TO ORIGINAL VALUE + } + } + this->emitTable(name, obj); // STORE this->op++; } break; @@ -1269,7 +1323,7 @@ void vm::evaluate() { // EVALUATE object::Map *map = new object::Map; // emit elements - for (int i = 0; i < count - 2; i++) { + for (int i = 0; i < count / 2; i++) { object::Object *y = POP(); object::Object *x = POP(); @@ -1333,7 +1387,14 @@ void vm::evaluate() { // EVALUATE case byte::FUNC: { // FUNCTION object::Func *f = static_cast(this->retConstant()); // OBJECT - this->emitTable(f->name, f); // STORE + + // ANONYMOUSE FUNCTION + if (f->name == "anonymouse") { + this->pushData(f); + break; + } + + this->emitTable(f->name, f); // STORE this->op++; } break; @@ -1382,7 +1443,7 @@ void vm::evaluate() { // EVALUATE // std::cout << "CALL ARGS: " << arguments.len() << std::endl; // ARGUMENT - for (std::map::reverse_iterator iter = + for (std::map::reverse_iterator iter = f->arguments.rbegin(); // REVERSE EMIT iter != f->arguments.rend(); iter++) { @@ -1694,6 +1755,16 @@ void vm::evaluate() { // EVALUATE this->op++; } break; + case byte::DEL: { // DEL + std::string name = this->retName(); + + if (this->lookUp(name) == nullptr) + error("not defined name '" + name + "'"); + + top()->tb.remove(name); + this->op++; + } break; + case byte::RET_N: // RET NONE case byte::RET: { // RETURN diff --git a/src/vm.h b/src/vm.h index 2b3f068..53688de 100644 --- a/src/vm.h +++ b/src/vm.h @@ -27,6 +27,7 @@ #include "opcode.h" #include "state.h" #include "util.h" +#include "type.h" // structure class vm { @@ -55,7 +56,7 @@ class vm { object::Object *retConstant(); // first to end iterator - ast::Type *retType(); + Type *retType(); // first to end iterator std::string retName(); @@ -64,13 +65,13 @@ class vm { int retOffset(); // are the comparison types the same - void typeChecker(ast::Type *, object::Object *); + void typeChecker(Type *, object::Object *); // are two values of same type equal bool objValueEquation(object::Object *, object::Object *); // generate default values - object::Object *setOriginalValue(ast::Type *); + object::Object *setOriginalValue(Type *); int op = 0; // offset pointer int lp = 0; @@ -93,6 +94,8 @@ class vm { inline void error(std::string); void newWhole(std::string, int, bool); // to execute the whole + void checkInterface(object::Whole *, + object::Whole *); // to check interface of whole public: explicit vm(Entity *m, std::vector *mods, bool replMode, diff --git a/std/os.ft b/std/os.ft index cdf841f..231d940 100644 --- a/std/os.ft +++ b/std/os.ft @@ -7,7 +7,7 @@ mod os */ def (desc: str, deep + op: int) loop do - let i: int = 0 + def i: int = 0 for -> if i == op out -> diff --git a/std/str.ft b/std/str.ft index f0279f1..0d2551d 100644 --- a/std/str.ft +++ b/std/str.ft @@ -1,31 +1,28 @@ mod str def Iter - /* - * return the count of character in string - */ def (char) *count -> int - def () *first -> char // return first char of string - def () *back -> char // return back char of string - def () *size -> int // return size of string + def () *first -> char + def () *back -> char + def () *size -> int end def And - def (str) *add -> str // add two string - def () *split -> []char // split string to array + def (str) *add -> str + def () *split -> []char end -def String <- Iter + And // implemention - def val: str // constructor +def String <- Iter + And + def val: str def (x: char) count -> int if len(val) == 0 ret 0 end do - def i: int // index - def c: int // count + def i: int + def c: int def l: int = len(val) for l > i @@ -34,30 +31,25 @@ def String <- Iter + And // implemention end l -= 1 end - ret c // return the count + ret c end - // add two string and return it def (x: str) add -> str - ret x + val + ret val + x end - // return first char of string def () first -> char ret val[0] end - // return back char of string def () back -> char ret val[len(val) - 1] end - // return size of string def () size -> int ret len(val) end - // split string def () split -> []char ret [val[0], val[1], val[2]] end diff --git a/test/fib.ft b/test/fib.ft index a9bad03..73a74fd 100644 --- a/test/fib.ft +++ b/test/fib.ft @@ -1,6 +1,12 @@ -def x: []int = [1, 2, 3] -def i: int = 0 +def x: [18]int = [1, 1] -x[i] = 88 +do + def i: int = 2 +for i < len(x) + x[i] = x[i - 1] + x[i - 2] + i += 1 +end -puts(i, x) \ No newline at end of file +del i + +puts(x) \ No newline at end of file diff --git a/test/fib2.ft b/test/fib2.ft new file mode 100644 index 0000000..77fc8b9 --- /dev/null +++ b/test/fib2.ft @@ -0,0 +1,11 @@ +def (n: int) fib -> int + if n == 0 + ret 0 + ef n == 1 + ret 1 + nf + ret fib(n - 1) + fib(n - 2) + end +end + +putl("fibonacci 20 = ", fib(20)) \ No newline at end of file diff --git a/test/local.ft b/test/local.ft index 90b64aa..768981a 100644 --- a/test/local.ft +++ b/test/local.ft @@ -2,10 +2,22 @@ if 1 > -1 def x: int = 45 + def p: int = 12 def () foo -> str ret "Hello World!!" end end -putl(x, foo()) \ No newline at end of file +// del p +// del foo + +putl(x, foo(), p) + +def Foo + def () call -> str + ret "Hello Drift!!" + end +end + +puts(new Foo.call(), foo()) \ No newline at end of file diff --git a/test/mark1.ft b/test/mark1.ft new file mode 100644 index 0000000..c7a2a22 --- /dev/null +++ b/test/mark1.ft @@ -0,0 +1,8 @@ +// MARK 1 + +do + def i: int = 0 +for i < 10000000 + putl("i = ", i) + i += 1 +end \ No newline at end of file diff --git a/test/mark1.py b/test/mark1.py new file mode 100644 index 0000000..8ed88f1 --- /dev/null +++ b/test/mark1.py @@ -0,0 +1,7 @@ +# MARK 1 + +i = 0 + +while i < 10000000: + print('i = %d' % i) + i += 1 \ No newline at end of file diff --git a/test/param.ft b/test/param.ft new file mode 100644 index 0000000..d5d5f26 --- /dev/null +++ b/test/param.ft @@ -0,0 +1,93 @@ +// NONE +def () foo + puts("CALL A") +end + +foo() + +// TUPLE +def (elem: (int)) foo + putl(len(elem), elem) +end + +foo((1, 2, 3)) + +// MAP +def (elem: ) foo + putl("len = ", len(elem), "elem = ", elem) +end + +foo({1: "OP", 4: "KL", 2: "US"}) + +// ARRAY +def (elem: []int) foo + putl(len(elem), elem) +end + +foo([1, 2, 3]) + +def Too + OK + NO +end + +def (elem: Too) foo -> Too + putl(elem) + ret elem +end + +puts(foo(Too.OK)) + +// FUNCTION +def (f: |int, int| -> float) op -> float + ret f(23, 46) +end + +def (a + b: int) add -> float + ret a + b +end + +def (a + b: int) sub -> float + ret a - b +end + +def (a + b: int) mul -> float + ret a * b +end + +def (a + b: int) div -> float + ret a / b +end + +putl(op(add), op(sub), op(mul), op(div)) + +// + +def () oop + puts("CALL!!") +end + +def (x: ||) what + putl(type(x), x) +end + +what(oop) + +// + +def (x: int) foo -> |int, int| -> []int + putl("x = ", x) + + ret def (a + b: int) -> []int + ret [ + a, + b, + a + b, + a - b, + a * b, + a / b + ] + end +end + +putl(foo(12)(3, 4)) \ No newline at end of file diff --git a/test/param2.ft b/test/param2.ft new file mode 100644 index 0000000..5b75705 --- /dev/null +++ b/test/param2.ft @@ -0,0 +1,6 @@ +// MAP +def (elem: ) foo + putl(len(elem), elem) +end + +foo({1: "OP", 4: "KL", 2: "US"}) \ No newline at end of file diff --git a/test/whole6.ft b/test/whole6.ft index d071306..c9d56a3 100644 --- a/test/whole6.ft +++ b/test/whole6.ft @@ -2,13 +2,24 @@ def Foo def (int) *add -> int def () f -> str - ret "X" + def x: int = -1 + + if x > 0 + ret "OK" + nf + ret "NO" + end end end def Bar <- Foo def () a -> str ret f() + //ret w() + end + + def () w -> str + ret "OP" end def (x: int) add -> int