Variable refactoring pt.1 - Change union to pointer.
This commit is contained in:
parent
5f168f8020
commit
996bef56a6
12 changed files with 258 additions and 105 deletions
2
Depfile
2
Depfile
|
@ -2,7 +2,7 @@
|
|||
Artifact=kernel
|
||||
TempDir=obj
|
||||
SourceDir=asm src
|
||||
Files=trainscript/trainscript.y trainscript/trainscript.l trainscript/tsvm.cpp
|
||||
Files=trainscript/trainscript.y trainscript/trainscript.l trainscript/tsvm.cpp trainscript/variable.cpp
|
||||
AdditionalObjects=obj/main.o
|
||||
|
||||
LexUseCpp
|
||||
|
|
17
Makefile
17
Makefile
|
@ -12,8 +12,8 @@ YACC = bison
|
|||
# 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 src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp
|
||||
OBJS = obj/tsvm.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 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
|
||||
|
||||
# Flags
|
||||
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
|
@ -27,10 +27,10 @@ all: kernel
|
|||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.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/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/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/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/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
|
||||
|
||||
# src/console.c
|
||||
obj/console.o: src/console.c include/console.h include/stdlib.h \
|
||||
|
@ -96,6 +96,13 @@ obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
|
|||
obj/trainscript.tab.hpp trainscript/trainscript.l.h include/string.h
|
||||
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/tsvm.cpp
|
||||
|
||||
# trainscript/variable.cpp
|
||||
obj/variable.o: trainscript/variable.cpp include/kernel.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
|
||||
|
||||
# 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
|
||||
|
|
21
README.md
21
README.md
|
@ -48,7 +48,26 @@ It also features a surveillance mode that logs all allocations / frees. It can b
|
|||
|0x20 - 0x27| IRQ0 - IRQ7 |
|
||||
|0x28 - 0x2F| IRQ8 - IRQ15 |
|
||||
|
||||
###
|
||||
## Virtual Machine Architecture
|
||||
|
||||
### Type Format
|
||||
The virtual machine supports 5 base types:
|
||||
|
||||
| Name | Description | Size |
|
||||
|---------|------------------------------------------------|--------|
|
||||
| Void | A type that specifies a non-existent value. | 0 |
|
||||
| Int | An integral number. | 32 |
|
||||
| Real | A decimal number. | 32/64¹ |
|
||||
| Text | A string value containing a sequence of bytes. | any² |
|
||||
| Bool | A boolen value, either `true` or `false`. | 1³ |
|
||||
|
||||
¹) A real number is either a float (32 bits) or a double (64 bits) depending on the configuration in `types.hpp`.
|
||||
²) A string value is sized the length of the string in bytes plus the size of the length specifier (32 bits).
|
||||
³) A boolean is representet as a 1 bit value but due to architecture limitations it is stored with 32 bits.
|
||||
|
||||
### Variable Format
|
||||
Variables are stored in a `type+pointer` format where `type` stores the type of the variable and `pointer` either a pointer to the variable value or, if `type` is a pointer type, the pointer value of the variable.
|
||||
|
||||
|
||||
## OS Architecture
|
||||
To be done.
|
||||
|
|
31
src/vm.cpp
31
src/vm.cpp
|
@ -82,33 +82,22 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
// Copy arguments
|
||||
size_t stackSize = 0;
|
||||
for(size_t i = 0; i < arguments.length(); i++) {
|
||||
if(arguments[i].type != this->parameters[i]) {
|
||||
if(arguments[i].type() != this->parameters[i]) {
|
||||
// die_extra("NativeMethod.InvalidArgumentType", arguments[i].type.name());
|
||||
}
|
||||
switch(arguments[i].type.id) {
|
||||
case TypeID::Bool: stackSize += sizeof(Int); break;
|
||||
case TypeID::Int: stackSize += sizeof(Int); break;
|
||||
case TypeID::Real: stackSize += sizeof(Real); break;
|
||||
default: die_extra("NativeMethod.InvalidArgument", arguments[i].type.name()); break;
|
||||
}
|
||||
stackSize += arguments[i].type().size();
|
||||
}
|
||||
|
||||
uint8_t *stack = (uint8_t*)malloc(stackSize);
|
||||
uint8_t *stackPtr = stack;
|
||||
for(size_t i = 0; i < arguments.length(); i++) {
|
||||
switch(arguments[i].type.id) {
|
||||
case TypeID::Bool:
|
||||
*reinterpret_cast<Int*>(stackPtr) = arguments[i].boolean ? 1 : 0;
|
||||
stackPtr += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Int:
|
||||
*reinterpret_cast<Int*>(stackPtr) = arguments[i].integer;
|
||||
stackPtr += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Real:
|
||||
*reinterpret_cast<Real*>(stackPtr) = arguments[i].real;
|
||||
stackPtr += sizeof(Real);
|
||||
break;
|
||||
|
||||
size_t size = arguments[i].type().size();
|
||||
void *data = arguments[i].data();
|
||||
|
||||
if(size > 0) {
|
||||
memcpy(stackPtr, data, size);
|
||||
stackPtr += size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +105,7 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
|
||||
free(stack);
|
||||
|
||||
return mkvar((Int)0);
|
||||
return Type::Int.createInstance();
|
||||
}
|
||||
|
||||
extern "C" void __cdecl printInt(int i) {
|
||||
|
|
|
@ -16,7 +16,8 @@ SOURCES += \
|
|||
src/timer.c \
|
||||
src/cplusplus.cpp \
|
||||
src/vm.cpp \
|
||||
src/serial.c
|
||||
src/serial.c \
|
||||
trainscript/variable.cpp
|
||||
|
||||
HEADERS += \
|
||||
include/console.h \
|
||||
|
|
|
@ -49,7 +49,7 @@ struct ParserData
|
|||
struct VariableDeclaration
|
||||
{
|
||||
char *name;
|
||||
trainscript::Variable variable;
|
||||
trainscript::Type type;
|
||||
};
|
||||
|
||||
struct LocalVariable
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace trainscript
|
|||
}
|
||||
|
||||
Type expectedResult(ExecutionContext &) const override {
|
||||
return this->value.type;
|
||||
return this->value.type();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ namespace trainscript
|
|||
if(var == nullptr) {
|
||||
return Type::Invalid;
|
||||
} else {
|
||||
return var->type;
|
||||
return var->type();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -109,18 +109,13 @@ namespace trainscript
|
|||
die_extra("VariableAssignmentExpression.VariableNotFound", this->variableName.str());
|
||||
}
|
||||
|
||||
if(target->type != result.type) {
|
||||
die_extra("VariableAssignmentExpression.ExpectedType", result.type.name());
|
||||
if(target->type() != result.type()) {
|
||||
die_extra("VariableAssignmentExpression.ExpectedType", result.type().name());
|
||||
}
|
||||
|
||||
switch(target->type.id) {
|
||||
case TypeID::Int: target->integer = result.integer; break;
|
||||
case TypeID::Real: target->real = result.real; break;
|
||||
case TypeID::Bool: target->boolean = result.boolean; break;
|
||||
default: break;
|
||||
}
|
||||
*target = result;
|
||||
|
||||
return result;
|
||||
return *target;
|
||||
}
|
||||
|
||||
bool validate(ExecutionContext &context, ker::String &errorCode) const override {
|
||||
|
@ -143,7 +138,7 @@ namespace trainscript
|
|||
errorCode = "Variable " + this->variableName + " not found.";
|
||||
return false;
|
||||
}
|
||||
if(var->type != result) {
|
||||
if(var->type() != result) {
|
||||
errorCode = "Variable assignment has invalid type.";
|
||||
return false;
|
||||
}
|
||||
|
@ -248,14 +243,14 @@ namespace trainscript
|
|||
Variable left = this->lhs->execute(context);
|
||||
Variable right = this->rhs->execute(context);
|
||||
|
||||
if(left.type != right.type) {
|
||||
if(left.type() != right.type()) {
|
||||
die("ArithmeticExpression.TypeMismatch");
|
||||
}
|
||||
|
||||
Variable result = OP(left, right);
|
||||
|
||||
if(result.type.usable() == false) {
|
||||
die_extra("ArithmeticExpression.InvalidResult", result.type.name());
|
||||
if(result.type().usable() == false) {
|
||||
die_extra("ArithmeticExpression.InvalidResult", result.type().name());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -324,13 +319,13 @@ namespace trainscript
|
|||
}
|
||||
|
||||
Variable result = this->condition->execute(context);
|
||||
if(result.type != Type::Boolean) {
|
||||
die_extra("IfExpression.TypeMismatch", result.type.name());
|
||||
if(result.type() != Type::Bool) {
|
||||
die_extra("IfExpression.TypeMismatch", result.type().name());
|
||||
}
|
||||
if((result.boolean == true) && (this->blockTrue != nullptr)) {
|
||||
if((result.value<Bool>() == true) && (this->blockTrue != nullptr)) {
|
||||
this->blockTrue->execute(context);
|
||||
}
|
||||
if((result.boolean == false) && (this->blockFalse != nullptr)) {
|
||||
if((result.value<Bool>() == false) && (this->blockFalse != nullptr)) {
|
||||
this->blockFalse->execute(context);
|
||||
}
|
||||
return Variable::Void;
|
||||
|
@ -389,10 +384,10 @@ namespace trainscript
|
|||
while(true)
|
||||
{
|
||||
Variable cond = this->condition->execute(context);
|
||||
if(cond.type != Type::Boolean) {
|
||||
if(cond.type() != Type::Bool) {
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if(cond.boolean == false) {
|
||||
if(cond.value<Bool>() == false) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ void yyerror(void *scanner, const char *s);
|
|||
input:
|
||||
%empty
|
||||
| input variableDeclaration SEMICOLON {
|
||||
auto *var = new Variable($2.variable);
|
||||
auto *var = new Variable($2.type.createInstance());
|
||||
context->module->variables.add( ker::String($2.name), var );
|
||||
}
|
||||
| input method {
|
||||
|
@ -328,9 +328,9 @@ elseIfLoop:
|
|||
;
|
||||
|
||||
expression:
|
||||
INT { $$ = new ConstantExpression(mkvar($1)); }
|
||||
| REAL { $$ = new ConstantExpression(mkvar($1)); }
|
||||
// | TEXT { $$ = new ConstantExpression(mkvar($1)); }
|
||||
INT { $$ = new ConstantExpression(Variable::fromInt($1)); }
|
||||
| REAL { $$ = new ConstantExpression(Variable::fromReal($1)); }
|
||||
// | TEXT { $$ = new ConstantExpression(Variable::fromText($1)); }
|
||||
| IDENTIFIER { $$ = new VariableExpression($1); }
|
||||
| IDENTIFIER LBRACKET expressionList RBRACKET {
|
||||
auto *call = new MethodInvokeExpression($1);
|
||||
|
@ -379,8 +379,7 @@ expressionList:
|
|||
variableDeclaration:
|
||||
KW_VAR IDENTIFIER COLON typeName {
|
||||
$$.name = $2;
|
||||
$$.variable.type = $4;
|
||||
$$.variable.integer = 0; // Initialize with zeroes
|
||||
$$.type = $4;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -15,14 +15,14 @@ namespace trainscript
|
|||
const Type Type::Int = { TypeID::Int, 0 };
|
||||
const Type Type::Real = { TypeID::Real, 0 };
|
||||
const Type Type::Text = { TypeID::Text, 0 };
|
||||
const Type Type::Boolean = { TypeID::Bool, 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::Boolean = { Type::Boolean, 0 };
|
||||
const Variable Variable::Bool = { Type::Bool, 0 };
|
||||
|
||||
bool Module::validate(ker::String &errorCode) const
|
||||
{
|
||||
|
@ -101,9 +101,7 @@ namespace trainscript
|
|||
context.add(var.first, var.second);
|
||||
}
|
||||
|
||||
Variable returnVariable = {
|
||||
this->mReturnValue.second, 0
|
||||
};
|
||||
Variable returnVariable = this->mReturnValue.second.createInstance();
|
||||
|
||||
if(this->mReturnValue.second.usable()) {
|
||||
context.add(this->mReturnValue.first, &returnVariable);
|
||||
|
@ -112,7 +110,7 @@ namespace trainscript
|
|||
die_extra("ScriptMethod::invoke", "Invalid argument count.");
|
||||
}
|
||||
for(size_t i = 0; i < this->mArguments.length(); i++) {
|
||||
if(this->mArguments[i].second != arguments[i].type) {
|
||||
if(this->mArguments[i].second != arguments[i].type()) {
|
||||
die_extra("ScriptMethod::invoke", "Invalid argument type.");
|
||||
}
|
||||
auto *v = new Variable(arguments[i]);
|
||||
|
@ -120,7 +118,7 @@ namespace trainscript
|
|||
context.add(this->mArguments[i].first, v);
|
||||
}
|
||||
for(auto local : this->mLocals) {
|
||||
auto *v = new Variable { local.second, 0 };
|
||||
auto *v = new Variable(local.second.createInstance());
|
||||
temporaries.append(v);
|
||||
context.add(local.first, v);
|
||||
}
|
||||
|
@ -148,9 +146,7 @@ namespace trainscript
|
|||
context.add(var.first, var.second);
|
||||
}
|
||||
|
||||
Variable returnVariable = {
|
||||
this->mReturnValue.second, 0
|
||||
};
|
||||
Variable returnVariable = this->mReturnValue.second.createInstance();
|
||||
|
||||
if(this->mReturnValue.second.usable()) {
|
||||
if(context.get(this->mReturnValue.first) != nullptr) {
|
||||
|
@ -165,14 +161,14 @@ namespace trainscript
|
|||
errorCode = "Parameter overlaps a variable.";
|
||||
return false;
|
||||
}
|
||||
context.add(this->mArguments[i].first, new Variable { this->mArguments[i].second, 0 });
|
||||
context.add(this->mArguments[i].first, new Variable(this->mArguments[i].second.createInstance()));
|
||||
}
|
||||
for(auto local : this->mLocals) {
|
||||
if(context.get(local.first) != nullptr) {
|
||||
errorCode = "Local variable overlaps a variable.";
|
||||
return false;
|
||||
}
|
||||
context.add(local.first, new Variable { local.second, 0 });
|
||||
context.add(local.first, new Variable(local.second.createInstance()));
|
||||
}
|
||||
|
||||
if(this->block->validate(context, errorCode) == false) {
|
||||
|
@ -184,6 +180,7 @@ namespace trainscript
|
|||
|
||||
namespace ops
|
||||
{
|
||||
/*
|
||||
Variable add(Variable lhs, Variable rhs)
|
||||
{
|
||||
switch(lhs.type.id) {
|
||||
|
@ -297,5 +294,7 @@ namespace trainscript
|
|||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
namespace trainscript
|
||||
{
|
||||
class Variable;
|
||||
|
||||
struct Type
|
||||
{
|
||||
TypeID id;
|
||||
|
@ -35,22 +37,49 @@ namespace trainscript
|
|||
}
|
||||
|
||||
const char *name() const {
|
||||
switch(id) {
|
||||
case TypeID::Invalid: return "INVALID";
|
||||
case TypeID::Void: return "VOID";
|
||||
case TypeID::Int: return "INT";
|
||||
case TypeID::Real: return "REAL";
|
||||
case TypeID::Text: return "TEXT";
|
||||
case TypeID::Bool: return "BOOL";
|
||||
default: return "unknown";
|
||||
if(this->pointer > 0) {
|
||||
static char str[64];
|
||||
strcpy(str, this->dereference().name());
|
||||
strcat(str, "*");
|
||||
return str;
|
||||
} else {
|
||||
switch(id) {
|
||||
case TypeID::Invalid: return "INVALID";
|
||||
case TypeID::Void: return "VOID";
|
||||
case TypeID::Int: return "INT";
|
||||
case TypeID::Real: return "REAL";
|
||||
case TypeID::Text: return "TEXT";
|
||||
case TypeID::Bool: return "BOOL";
|
||||
default: return "<UNKNOWN>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
if(this->pointer > 0) {
|
||||
return sizeof(void*);
|
||||
} else {
|
||||
switch(id) {
|
||||
case TypeID::Invalid: return 0;
|
||||
case TypeID::Void: return 0;
|
||||
case TypeID::Int: return sizeof(Int);
|
||||
case TypeID::Real: return sizeof(Real);
|
||||
case TypeID::Text: return sizeof(Text);
|
||||
case TypeID::Bool: return sizeof(Bool);
|
||||
default: die("Type::size.UnknownTypeID");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Variable createInstance() const;
|
||||
|
||||
static const Type Invalid;
|
||||
static const Type Void;
|
||||
static const Type Int;
|
||||
static const Type Real;
|
||||
static const Type Text;
|
||||
static const Type Boolean;
|
||||
static const Type Bool;
|
||||
};
|
||||
}
|
||||
|
|
77
trainscript/variable.cpp
Normal file
77
trainscript/variable.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include <kernel.h>
|
||||
#include "variable.hpp"
|
||||
|
||||
namespace trainscript
|
||||
{
|
||||
Variable::~Variable()
|
||||
{
|
||||
// Only free non-pointer types.
|
||||
if(this->mType.pointer == 0) {
|
||||
switch(this->mType.id) {
|
||||
#define DELETE(type) case TypeID::type: \
|
||||
delete reinterpret_cast<trainscript::type*>(this->mValue); \
|
||||
break
|
||||
DELETE(Bool);
|
||||
DELETE(Int);
|
||||
DELETE(Real);
|
||||
DELETE(Text);
|
||||
#undef DELETE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variable &Variable::operator =(const Variable &other)
|
||||
{
|
||||
if(this->mType != other.mType) {
|
||||
die_extra("Variable.operator=", "Type mismatch.");
|
||||
}
|
||||
if(this->mType.pointer == 0) {
|
||||
switch(this->mType.id) {
|
||||
#define COPY(type) case TypeID::type: \
|
||||
*reinterpret_cast<trainscript::type*>(this->mValue) = *reinterpret_cast<trainscript::type*>(other.mValue); \
|
||||
break
|
||||
COPY(Bool);
|
||||
COPY(Int);
|
||||
COPY(Real);
|
||||
COPY(Text);
|
||||
#undef COPY
|
||||
}
|
||||
} else {
|
||||
this->mValue = other.mValue;
|
||||
}
|
||||
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) \
|
||||
{ \
|
||||
Variable var = Type::type.createInstance(); \
|
||||
var.value<trainscript::type>() = i; \
|
||||
return var; \
|
||||
}
|
||||
|
||||
fromType(Int)
|
||||
fromType(Real)
|
||||
fromType(Text)
|
||||
fromType(Bool)
|
||||
}
|
|
@ -5,15 +5,66 @@
|
|||
|
||||
namespace trainscript
|
||||
{
|
||||
struct Variable
|
||||
class Variable
|
||||
{
|
||||
Type type;
|
||||
union {
|
||||
Int integer;
|
||||
Real real;
|
||||
// Text text;
|
||||
Bool boolean;
|
||||
};
|
||||
friend class Type;
|
||||
private:
|
||||
Type mType;
|
||||
void *mValue;
|
||||
private:
|
||||
// To be called by Type::createInstance
|
||||
Variable(const Type &type, void *value) :
|
||||
mType(type),
|
||||
mValue(value)
|
||||
{
|
||||
|
||||
}
|
||||
public:
|
||||
Variable() :
|
||||
mType(Type::Invalid),
|
||||
mValue(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable(const Variable &other) :
|
||||
mType(other.mType),
|
||||
mValue(nullptr)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Variable(Variable &&other) :
|
||||
mType(other.mType),
|
||||
mValue(other.mValue)
|
||||
{
|
||||
other.mType = Type::Invalid;
|
||||
other.mValue = nullptr;
|
||||
}
|
||||
~Variable();
|
||||
|
||||
Variable &operator =(const Variable &other);
|
||||
|
||||
void *data() const
|
||||
{
|
||||
return this->mValue;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& value()
|
||||
{
|
||||
return *reinterpret_cast<T*>(this->mValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& value() const
|
||||
{
|
||||
return *reinterpret_cast<T*>(this->mValue);
|
||||
}
|
||||
|
||||
const Type &type() const {
|
||||
return this->mType;
|
||||
}
|
||||
|
||||
#if defined(TSVM_PRINTVAL)
|
||||
void printval() const
|
||||
|
@ -27,29 +78,16 @@ namespace trainscript
|
|||
}
|
||||
#endif
|
||||
|
||||
static Variable fromInt(trainscript::Int i);
|
||||
static Variable fromReal(trainscript::Real r);
|
||||
static Variable fromText(trainscript::Text t);
|
||||
static Variable fromBool(Bool b);
|
||||
|
||||
static const Variable Invalid;
|
||||
static const Variable Void;
|
||||
static const Variable Int;
|
||||
static const Variable Real;
|
||||
static const Variable Text;
|
||||
static const Variable Boolean;
|
||||
static const Variable Bool;
|
||||
};
|
||||
|
||||
static inline Variable mkvar(Int value) {
|
||||
Variable v = Variable::Int;
|
||||
v.integer = value;
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Variable mkvar(Real value) {
|
||||
Variable v = Variable::Real;
|
||||
v.real = value;
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Variable mkbool(Bool value) {
|
||||
Variable v = Variable::Boolean;
|
||||
v.boolean = value;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue