Refactors type system: Types now provide operators instead of prebuilt ones. Known bug: Second parameter gets lost.
This commit is contained in:
parent
996bef56a6
commit
2e858d8d91
11 changed files with 306 additions and 206 deletions
5
Depfile
5
Depfile
|
@ -2,7 +2,9 @@
|
|||
Artifact=kernel
|
||||
TempDir=obj
|
||||
SourceDir=asm src
|
||||
Files=trainscript/trainscript.y trainscript/trainscript.l trainscript/tsvm.cpp trainscript/variable.cpp
|
||||
Files=trainscript/trainscript.y trainscript/trainscript.l
|
||||
Files=trainscript/tsvm.cpp trainscript/variable.cpp trainscript/type.cpp
|
||||
Files=trainscript/type-operators.cpp.tt
|
||||
AdditionalObjects=obj/main.o
|
||||
|
||||
LexUseCpp
|
||||
|
@ -15,6 +17,7 @@ CXX=g++
|
|||
LD=g++
|
||||
LEX=flex
|
||||
YACC=bison
|
||||
TEMPLE=mono /home/felix/projects/temple/bin/Debug/temple.exe
|
||||
|
||||
# Flags
|
||||
FLAGS=-m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
|
|
31
Makefile
31
Makefile
|
@ -8,12 +8,13 @@ CXX = g++
|
|||
LD = g++
|
||||
LEX = flex
|
||||
YACC = bison
|
||||
TEMPLE = mono /home/felix/projects/temple/bin/Debug/temple.exe
|
||||
|
||||
# File Lists
|
||||
SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S
|
||||
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/serial.c src/stdlib.c src/timer.c src/vmm.c
|
||||
SRCS_CXX = trainscript/tsvm.cpp trainscript/variable.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp
|
||||
OBJS = obj/tsvm.o obj/variable.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
SRCS_CXX = trainscript/tsvm.cpp trainscript/variable.cpp trainscript/type.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/type-operators.cpp
|
||||
OBJS = obj/tsvm.o obj/variable.o obj/type.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/type-operators.o obj/main.o
|
||||
|
||||
# Flags
|
||||
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
|
@ -27,10 +28,10 @@ all: kernel
|
|||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/variable.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/type-operators.cpp obj/tsvm.o obj/variable.o obj/type.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/type-operators.o obj/main.o
|
||||
|
||||
kernel: obj/tsvm.o obj/variable.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/variable.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
kernel: obj/tsvm.o obj/variable.o obj/type.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/type-operators.o obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/variable.o obj/type.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/type-operators.o obj/main.o
|
||||
|
||||
# src/console.c
|
||||
obj/console.o: src/console.c include/console.h include/stdlib.h \
|
||||
|
@ -97,12 +98,19 @@ obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
|
|||
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/tsvm.cpp
|
||||
|
||||
# trainscript/variable.cpp
|
||||
obj/variable.o: trainscript/variable.cpp include/kernel.h \
|
||||
obj/variable.o: trainscript/variable.cpp include/kernel.h include/console.h \
|
||||
trainscript/variable.hpp trainscript/type.hpp trainscript/types.hpp \
|
||||
include/ker/string.hpp include/stdlib.h include/varargs.h \
|
||||
include/config.h include/malloc.h trainscript/typeid.hpp
|
||||
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/variable.cpp
|
||||
|
||||
# trainscript/type.cpp
|
||||
obj/type.o: trainscript/type.cpp include/kernel.h include/console.h \
|
||||
trainscript/type.hpp trainscript/types.hpp include/ker/string.hpp \
|
||||
include/stdlib.h include/varargs.h include/config.h include/malloc.h \
|
||||
trainscript/typeid.hpp trainscript/variable.hpp
|
||||
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/type.cpp
|
||||
|
||||
# src/cplusplus.cpp
|
||||
obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
|
||||
include/config.h include/malloc.h include/console.h include/ker/new.hpp
|
||||
|
@ -149,6 +157,14 @@ obj/trainscript.tab.o: obj/trainscript.tab.cpp include/stdlib.h \
|
|||
trainscript/trainscript.l.h include/string.h
|
||||
$(CXX) -iquotetrainscript -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp
|
||||
|
||||
# obj/type-operators.cpp
|
||||
obj/type-operators.o: obj/type-operators.cpp include/kernel.h \
|
||||
include/console.h trainscript/type.hpp trainscript/types.hpp \
|
||||
include/ker/string.hpp include/stdlib.h include/varargs.h \
|
||||
include/config.h include/malloc.h trainscript/typeid.hpp \
|
||||
trainscript/variable.hpp
|
||||
$(CXX) -iquotetrainscript -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c obj/type-operators.cpp
|
||||
|
||||
# asm/dynamic.S
|
||||
obj/dynamic.o: asm/dynamic.S
|
||||
$(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/dynamic.S
|
||||
|
@ -171,6 +187,9 @@ obj/trainscript.yy.cpp: trainscript/trainscript.l
|
|||
obj/trainscript.tab.cpp: trainscript/trainscript.y
|
||||
$(YACC) -o obj/trainscript.tab.cpp -d trainscript/trainscript.y
|
||||
|
||||
obj/type-operators.cpp: trainscript/type-operators.cpp.tt
|
||||
$(TEMPLE) trainscript/type-operators.cpp.tt obj/type-operators.cpp
|
||||
|
||||
# Custom Targets
|
||||
obj/main.o: scripts/main.ts
|
||||
objcopy -B i386 -I binary -O elf32-i386 \
|
||||
|
|
|
@ -17,7 +17,8 @@ SOURCES += \
|
|||
src/cplusplus.cpp \
|
||||
src/vm.cpp \
|
||||
src/serial.c \
|
||||
trainscript/variable.cpp
|
||||
trainscript/variable.cpp \
|
||||
trainscript/type.cpp
|
||||
|
||||
HEADERS += \
|
||||
include/console.h \
|
||||
|
@ -72,7 +73,8 @@ DISTFILES += \
|
|||
Makefile.new \
|
||||
scripts/main.ts \
|
||||
asm/dynamic.S \
|
||||
README.md
|
||||
README.md \
|
||||
trainscript/type-operators.cpp.tt
|
||||
|
||||
QMAKE_INCDIR =
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace trainscript
|
|||
{
|
||||
public:
|
||||
Variable value;
|
||||
ConstantExpression(Variable value) : value(value) { }
|
||||
ConstantExpression(const Variable &value) : value(value) { }
|
||||
|
||||
Variable execute(ExecutionContext &) const override {
|
||||
return this->value;
|
||||
|
@ -179,7 +179,7 @@ namespace trainscript
|
|||
ker::Vector<Variable> vars(this->parameters.length());
|
||||
vars.resize(this->parameters.length());
|
||||
for(size_t i = 0; i < vars.length(); i++) {
|
||||
vars[i] = this->parameters.at(i)->execute(context);
|
||||
vars[i].replace(this->parameters.at(i)->execute(context));
|
||||
}
|
||||
|
||||
return method->invoke(vars);
|
||||
|
@ -218,14 +218,15 @@ namespace trainscript
|
|||
}
|
||||
};
|
||||
|
||||
template<Variable (*OP)(Variable, Variable)>
|
||||
class ArithmeticExpression :
|
||||
public Instruction
|
||||
{
|
||||
public:
|
||||
Operation op;
|
||||
Instruction *lhs, *rhs;
|
||||
|
||||
ArithmeticExpression(Instruction *lhs, Instruction *rhs) :
|
||||
ArithmeticExpression(Instruction *lhs, Instruction *rhs, Operation op) :
|
||||
op(op),
|
||||
lhs(lhs),
|
||||
rhs(rhs)
|
||||
{
|
||||
|
@ -247,7 +248,11 @@ namespace trainscript
|
|||
die("ArithmeticExpression.TypeMismatch");
|
||||
}
|
||||
|
||||
Variable result = OP(left, right);
|
||||
if(left.type().hasOperator(this->op) == false) {
|
||||
die_extra("ArithmeticExpression.InvalidOperator", "The operator was not defined for this type.");
|
||||
}
|
||||
|
||||
Variable result = left.type().apply(left, this->op, right);
|
||||
|
||||
if(result.type().usable() == false) {
|
||||
die_extra("ArithmeticExpression.InvalidResult", result.type().name());
|
||||
|
@ -280,6 +285,11 @@ namespace trainscript
|
|||
return false;
|
||||
}
|
||||
|
||||
if(lhsType.hasOperator(this->op) == false) {
|
||||
errorCode = "The operator is not defined for this type.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this->lhs->validate(context, errorCode) == false)
|
||||
return false;
|
||||
if(this->rhs->validate(context, errorCode) == false)
|
||||
|
|
|
@ -9,23 +9,6 @@
|
|||
|
||||
using namespace trainscript;
|
||||
|
||||
namespace trainscript {
|
||||
namespace ops {
|
||||
Variable add(Variable lhs, Variable rhs);
|
||||
Variable subtract(Variable lhs, Variable rhs);
|
||||
Variable multiply(Variable lhs, Variable rhs);
|
||||
Variable divide(Variable lhs, Variable rhs);
|
||||
Variable modulo(Variable lhs, Variable rhs);
|
||||
|
||||
Variable equals(Variable lhs, Variable rhs);
|
||||
Variable inequals(Variable lhs, Variable rhs);
|
||||
Variable less(Variable lhs, Variable rhs);
|
||||
Variable lessEqual(Variable lhs, Variable rhs);
|
||||
Variable greater(Variable lhs, Variable rhs);
|
||||
Variable greaterEqual(Variable lhs, Variable rhs);
|
||||
}
|
||||
}
|
||||
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
|
||||
// stuff from flex that bison needs to know about:
|
||||
|
@ -162,12 +145,16 @@ input:
|
|||
LocalVariable *local = $2.header.locals;
|
||||
while(local) {
|
||||
method->mLocals.add( local->name, local->type );
|
||||
LocalVariable *tmp = local;
|
||||
local = local->next;
|
||||
delete tmp;
|
||||
}
|
||||
LocalVariable *arg = $2.header.arguments;
|
||||
while(arg) {
|
||||
method->mArguments.append( { arg->name, arg->type} );
|
||||
LocalVariable *tmp = local;
|
||||
arg = arg->next;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
context->module->methods.add( $2.header.name, method );
|
||||
|
@ -189,7 +176,9 @@ block:
|
|||
if(mb->instruction != nullptr) {
|
||||
block->instructions.append(mb->instruction);
|
||||
}
|
||||
MethodBody *tmp = mb;
|
||||
mb = mb->next;
|
||||
delete mb;
|
||||
}
|
||||
$$ = block;
|
||||
}
|
||||
|
@ -342,17 +331,17 @@ expression:
|
|||
$$ = call;
|
||||
}
|
||||
| LBRACKET expression RBRACKET { $$ = $2; }
|
||||
| expression PLUS expression { $$ = new ArithmeticExpression<trainscript::ops::add>($1, $3); }
|
||||
| expression MINUS expression { $$ = new ArithmeticExpression<trainscript::ops::subtract>($1, $3); }
|
||||
| expression MULTIPLY expression { $$ = new ArithmeticExpression<trainscript::ops::multiply>($1, $3); }
|
||||
| expression DIVIDE expression { $$ = new ArithmeticExpression<trainscript::ops::divide>($1, $3); }
|
||||
| expression MODULO expression { $$ = new ArithmeticExpression<trainscript::ops::modulo>($1, $3); }
|
||||
| expression OP_LT expression { $$ = new ArithmeticExpression<trainscript::ops::less>($1, $3); }
|
||||
| expression OP_LE expression { $$ = new ArithmeticExpression<trainscript::ops::lessEqual>($1, $3); }
|
||||
| expression OP_GT expression { $$ = new ArithmeticExpression<trainscript::ops::greater>($1, $3); }
|
||||
| expression OP_GE expression { $$ = new ArithmeticExpression<trainscript::ops::greaterEqual>($1, $3); }
|
||||
| expression OP_EQ expression { $$ = new ArithmeticExpression<trainscript::ops::equals>($1, $3); }
|
||||
| expression OP_NEQ expression { $$ = new ArithmeticExpression<trainscript::ops::inequals>($1, $3); }
|
||||
| expression PLUS expression { $$ = new ArithmeticExpression($1, $3, Operation::Add); }
|
||||
| expression MINUS expression { $$ = new ArithmeticExpression($1, $3, Operation::Subtract); }
|
||||
| expression MULTIPLY expression { $$ = new ArithmeticExpression($1, $3, Operation::Multiply); }
|
||||
| expression DIVIDE expression { $$ = new ArithmeticExpression($1, $3, Operation::Divide); }
|
||||
| expression MODULO expression { $$ = new ArithmeticExpression($1, $3, Operation::Modulo); }
|
||||
| expression OP_LT expression { $$ = new ArithmeticExpression($1, $3, Operation::Less); }
|
||||
| expression OP_LE expression { $$ = new ArithmeticExpression($1, $3, Operation::LessEquals); }
|
||||
| expression OP_GT expression { $$ = new ArithmeticExpression($1, $3, Operation::Greater); }
|
||||
| expression OP_GE expression { $$ = new ArithmeticExpression($1, $3, Operation::GreaterEquals); }
|
||||
| expression OP_EQ expression { $$ = new ArithmeticExpression($1, $3, Operation::Equals); }
|
||||
| expression OP_NEQ expression { $$ = new ArithmeticExpression($1, $3, Operation::Inequals); }
|
||||
| expression RARROW IDENTIFIER { $$ = new VariableAssignmentExpression($3, $1); }
|
||||
;
|
||||
|
||||
|
@ -384,12 +373,12 @@ variableDeclaration:
|
|||
;
|
||||
|
||||
typeName:
|
||||
KW_VOID { $$.id = TypeID::Void; $$.pointer = 0; }
|
||||
| KW_INT { $$.id = TypeID::Int; $$.pointer = 0; }
|
||||
| KW_REAL { $$.id = TypeID::Real; $$.pointer = 0; }
|
||||
| KW_TEXT { $$.id = TypeID::Text; $$.pointer = 0; }
|
||||
| KW_BOOL { $$.id = TypeID::Bool; $$.pointer = 0; }
|
||||
| KW_PTR LBRACKET typeName RBRACKET { $$ = $3; $$.pointer++; }
|
||||
KW_VOID { $$ = Type::Void; }
|
||||
| KW_INT { $$ = Type::Int; }
|
||||
| KW_REAL { $$ = Type::Real; }
|
||||
| KW_TEXT { $$ = Type::Text; }
|
||||
| KW_BOOL { $$ = Type::Bool; }
|
||||
| KW_PTR LBRACKET typeName RBRACKET { $$ = $3.reference(); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
@ -10,20 +10,6 @@
|
|||
|
||||
namespace trainscript
|
||||
{
|
||||
const Type Type::Invalid = { TypeID::Invalid, 0 };
|
||||
const Type Type::Void = { TypeID::Void, 0 };
|
||||
const Type Type::Int = { TypeID::Int, 0 };
|
||||
const Type Type::Real = { TypeID::Real, 0 };
|
||||
const Type Type::Text = { TypeID::Text, 0 };
|
||||
const Type Type::Bool = { TypeID::Bool, 0 };
|
||||
|
||||
const Variable Variable::Invalid = { Type::Invalid, 0 };
|
||||
const Variable Variable::Void = { Type::Void, 0 };
|
||||
const Variable Variable::Int = { Type::Int, 0 };
|
||||
const Variable Variable::Real = { Type::Real, 0 };
|
||||
const Variable Variable::Text = { Type::Text, 0 };
|
||||
const Variable Variable::Bool = { Type::Bool, 0 };
|
||||
|
||||
bool Module::validate(ker::String &errorCode) const
|
||||
{
|
||||
errorCode = "";
|
||||
|
@ -177,124 +163,4 @@ namespace trainscript
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace ops
|
||||
{
|
||||
/*
|
||||
Variable add(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int:return mkvar(lhs.integer + rhs.integer);
|
||||
case TypeID::Real: return mkvar(lhs.real + rhs.real);
|
||||
default: kprintf("addition not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable subtract(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkvar(lhs.integer - rhs.integer);
|
||||
case TypeID::Real:return mkvar(lhs.real - rhs.real);
|
||||
default: kprintf("subtraction not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable multiply(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkvar(lhs.integer * rhs.integer);
|
||||
case TypeID::Real: return mkvar(lhs.real * rhs.real);
|
||||
default: kprintf("multiplication not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable divide(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkvar(lhs.integer / rhs.integer);
|
||||
case TypeID::Real: return mkvar(lhs.real / rhs.real);
|
||||
default: kprintf("division not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable modulo(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkvar(lhs.integer % rhs.integer);
|
||||
// case TypeID::Real: mkvar(lhs.real % rhs.real);
|
||||
default: kprintf("modulo not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable equals(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer == rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real == rhs.real);
|
||||
case TypeID::Bool: return mkbool(lhs.boolean == rhs.boolean);
|
||||
default:
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable inequals(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer != rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real != rhs.real);
|
||||
case TypeID::Bool: return mkbool(lhs.boolean != rhs.boolean);
|
||||
default:
|
||||
kprintf("inequals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Variable less(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer < rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real < rhs.real);
|
||||
default:
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable lessEqual(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer <= rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real <= rhs.real);
|
||||
default:
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable greater(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer > rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real > rhs.real);
|
||||
default:
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
Variable greaterEqual(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
case TypeID::Int: return mkbool(lhs.integer >= rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real >= rhs.real);
|
||||
default:
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
89
trainscript/type-operators.cpp.tt
Normal file
89
trainscript/type-operators.cpp.tt
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <kernel.h>
|
||||
#include <console.h>
|
||||
#include "type.hpp"
|
||||
#include "variable.hpp"<?
|
||||
ops = {
|
||||
{ "add" },
|
||||
{ "subtract" },
|
||||
{ "multiply" },
|
||||
{ "divide" },
|
||||
{ "modulo" },
|
||||
{ "lt", "Bool" },
|
||||
{ "le", "Bool" },
|
||||
{ "gt", "Bool" },
|
||||
{ "ge", "Bool" },
|
||||
{ "eq", "Bool" },
|
||||
{ "ieq", "Bool" },
|
||||
}
|
||||
types = {
|
||||
Invalid = { }, -- no operators at all, all nil
|
||||
Int = {
|
||||
add = "+",
|
||||
subtract = "-",
|
||||
multiply = "*",
|
||||
divide = "/",
|
||||
modulo = "%",
|
||||
lt = "<",
|
||||
le = "<=",
|
||||
gt = ">",
|
||||
ge = ">=",
|
||||
eq = "==",
|
||||
ieq = "!="
|
||||
},
|
||||
Real = {
|
||||
add = "+",
|
||||
subtract = "-",
|
||||
multiply = "*",
|
||||
divide = "/",
|
||||
lt = "<",
|
||||
le = "<=",
|
||||
gt = ">",
|
||||
ge = ">=",
|
||||
eq = "==",
|
||||
ieq = "!="
|
||||
},
|
||||
Bool = {
|
||||
add = "||",
|
||||
multiply = "&&",
|
||||
eq = "==",
|
||||
ieq = "!="
|
||||
},
|
||||
Text = {
|
||||
add = "+",
|
||||
eq = "==",
|
||||
ieq = "!="
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
namespace trainscript
|
||||
{
|
||||
<? for type,desc in pairs(types) do
|
||||
for _, _op in ipairs(ops) do
|
||||
local op = _op[1]
|
||||
local rt = _op[2] or type
|
||||
if desc[op] then
|
||||
local name = type .. "_" .. op;
|
||||
local sign = desc[op];
|
||||
?>static Variable <[name]>(const Variable &lhs, const Variable &rhs)
|
||||
{
|
||||
return Variable::from<[rt]>(lhs.value<<[type]>>() <[sign]> rhs.value<<[type]>>());
|
||||
}
|
||||
<? end
|
||||
end
|
||||
end
|
||||
for type,desc in pairs(types) do ?>
|
||||
TypeOps <[type]>Operators = {<?
|
||||
for _, _op in ipairs(ops) do
|
||||
local op = _op[1] ?>
|
||||
<?
|
||||
if desc[op] == nil then
|
||||
?>nullptr,<?
|
||||
else
|
||||
?><[type]>_<[op]>,<?
|
||||
end
|
||||
end ?>
|
||||
};<? end ?>
|
||||
}
|
||||
|
41
trainscript/type.cpp
Normal file
41
trainscript/type.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include <kernel.h>
|
||||
#include <console.h>
|
||||
#include "type.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
namespace trainscript
|
||||
{
|
||||
extern TypeOps InvalidOperators;
|
||||
extern TypeOps IntOperators;
|
||||
extern TypeOps RealOperators;
|
||||
extern TypeOps TextOperators;
|
||||
extern TypeOps BoolOperators;
|
||||
|
||||
const Type Type::Invalid = { TypeID::Invalid, 0, &InvalidOperators };
|
||||
const Type Type::Void = { TypeID::Void, 0, &InvalidOperators };
|
||||
const Type Type::Int = { TypeID::Int, 0, &IntOperators };
|
||||
const Type Type::Real = { TypeID::Real, 0, &RealOperators };
|
||||
const Type Type::Text = { TypeID::Text, 0, &TextOperators };
|
||||
const Type Type::Bool = { TypeID::Bool, 0, &BoolOperators };
|
||||
|
||||
bool Type::hasOperator(Operation op) const
|
||||
{
|
||||
return this->operators->ops[(int)op] != nullptr;
|
||||
}
|
||||
|
||||
Variable Type::apply(const Variable &lhs, Operation op, const Variable &rhs) const
|
||||
{
|
||||
if(this->hasOperator(op) == false) {
|
||||
kprintf("[invalid op: apply %d to %s]", (int)op, this->name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
return this->operators->ops[(int)op](lhs, rhs);
|
||||
}
|
||||
|
||||
Variable Type::createInstance() const
|
||||
{
|
||||
Variable v;
|
||||
v.setType(*this);
|
||||
return v;
|
||||
}
|
||||
}
|
|
@ -8,17 +8,40 @@ namespace trainscript
|
|||
{
|
||||
class Variable;
|
||||
|
||||
using Operator = Variable (*)(const Variable & rhs, const Variable &lhs);
|
||||
|
||||
enum class Operation
|
||||
{
|
||||
Add = 0,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Modulo,
|
||||
Less,
|
||||
LessEquals,
|
||||
Greater,
|
||||
GreaterEquals,
|
||||
Equals,
|
||||
Inequals,
|
||||
LIMIT
|
||||
};
|
||||
|
||||
struct TypeOps {
|
||||
Operator ops[(int)Operation::LIMIT];
|
||||
};
|
||||
|
||||
struct Type
|
||||
{
|
||||
TypeID id;
|
||||
int pointer;
|
||||
const TypeOps *operators;
|
||||
|
||||
Type reference() const {
|
||||
return { id, pointer + 1 };
|
||||
return Type { id, pointer + 1, operators };
|
||||
}
|
||||
|
||||
Type dereference() const {
|
||||
return { id, pointer - 1 };
|
||||
return Type { id, pointer - 1, operators };
|
||||
}
|
||||
|
||||
bool usable() const {
|
||||
|
@ -73,8 +96,28 @@ namespace trainscript
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates an instance of this type.
|
||||
* @return Variable with a value of this type.
|
||||
*/
|
||||
Variable createInstance() const;
|
||||
|
||||
/**
|
||||
* @brief Checks if the type has the operation defined.
|
||||
* @param op Operation that should be checked
|
||||
* @return True if the operation is defined, else false
|
||||
*/
|
||||
bool hasOperator(Operation op) const;
|
||||
|
||||
/**
|
||||
* @brief Applies the operation to the operands.
|
||||
* @param lhs Left hand side
|
||||
* @param op Operation
|
||||
* @param rhs Right hand side
|
||||
* @return Result of the operation or Variable::Invalid if operation is not defined.
|
||||
*/
|
||||
Variable apply(const Variable &lhs, Operation op, const Variable &rhs) const;
|
||||
|
||||
static const Type Invalid;
|
||||
static const Type Void;
|
||||
static const Type Int;
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
#include <kernel.h>
|
||||
#include <console.h>
|
||||
#include "variable.hpp"
|
||||
#include "type.hpp"
|
||||
|
||||
namespace trainscript
|
||||
{
|
||||
const Variable Variable::Invalid = { Type::Invalid, 0 };
|
||||
const Variable Variable::Void = { Type::Void, 0 };
|
||||
const Variable Variable::Int = { Type::Int, 0 };
|
||||
const Variable Variable::Real = { Type::Real, 0 };
|
||||
const Variable Variable::Text = { Type::Text, 0 };
|
||||
const Variable Variable::Bool = { Type::Bool, 0 };
|
||||
|
||||
Variable::~Variable()
|
||||
{
|
||||
// Only free non-pointer types.
|
||||
|
@ -20,11 +29,51 @@ namespace trainscript
|
|||
}
|
||||
}
|
||||
|
||||
void Variable::replace(const Variable &other)
|
||||
{
|
||||
this->setType(other.mType);
|
||||
*this = other;
|
||||
}
|
||||
|
||||
void Variable::setType(const Type &type)
|
||||
{
|
||||
this->mType = type;
|
||||
this->mValue = nullptr;
|
||||
if(mType.pointer == 0) {
|
||||
switch(mType.id) {
|
||||
#define CREATE(type, initial) case TypeID::type: \
|
||||
this->mValue = new trainscript::type(initial); \
|
||||
break
|
||||
CREATE(Bool, false);
|
||||
CREATE(Int, 0);
|
||||
CREATE(Real, 0.0);
|
||||
CREATE(Text, "");
|
||||
#undef CREATE
|
||||
case TypeID::Invalid:
|
||||
case TypeID::Void:
|
||||
// Ignore INVALID or VOID type.
|
||||
break;
|
||||
default:
|
||||
die_extra("Variable::setType.InvalidTypeID", mType.name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variable &Variable::operator =(const Variable &other)
|
||||
{
|
||||
if(this->mType != other.mType) {
|
||||
kprintf("[%s -> %s]", other.mType.name(), this->mType.name());
|
||||
die_extra("Variable.operator=", "Type mismatch.");
|
||||
}
|
||||
if(this->mType == Type::Void) {
|
||||
// Just don't do anything when assigning void.
|
||||
return *this;
|
||||
}
|
||||
if(this->mValue == nullptr) {
|
||||
kprintf("[Variable.type: %s]", this->mType.name());
|
||||
die_extra("Variable.operator=", "Invalid variable: value == nullptr");
|
||||
}
|
||||
if(this->mType.pointer == 0) {
|
||||
switch(this->mType.id) {
|
||||
#define COPY(type) case TypeID::type: \
|
||||
|
@ -42,26 +91,6 @@ namespace trainscript
|
|||
return *this;
|
||||
}
|
||||
|
||||
Variable Type::createInstance() const
|
||||
{
|
||||
void *value = nullptr;
|
||||
if(this->pointer > 0) {
|
||||
switch(this->id) {
|
||||
#define CREATE(type, initial) case TypeID::type: \
|
||||
value = new trainscript::type(initial); \
|
||||
break
|
||||
CREATE(Bool, false);
|
||||
CREATE(Int, 0);
|
||||
CREATE(Real, 0.0);
|
||||
CREATE(Text, "");
|
||||
default:
|
||||
die("Type::createInstance.InvalidTypeID");
|
||||
}
|
||||
}
|
||||
|
||||
return Variable(*this, value);
|
||||
}
|
||||
|
||||
|
||||
#define fromType(type) Variable Variable::from##type(trainscript::type i) \
|
||||
{ \
|
||||
|
|
|
@ -28,9 +28,10 @@ namespace trainscript
|
|||
}
|
||||
|
||||
Variable(const Variable &other) :
|
||||
mType(other.mType),
|
||||
mValue(nullptr)
|
||||
mType(),
|
||||
mValue()
|
||||
{
|
||||
this->setType(other.mType);
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
@ -45,6 +46,14 @@ namespace trainscript
|
|||
|
||||
Variable &operator =(const Variable &other);
|
||||
|
||||
/**
|
||||
* @brief Replaces the value and type of this variable.
|
||||
* @param other The reference variable to copy.
|
||||
*/
|
||||
void replace(const Variable &other);
|
||||
|
||||
void setType(const Type &type);
|
||||
|
||||
void *data() const
|
||||
{
|
||||
return this->mValue;
|
||||
|
|
Loading…
Reference in a new issue