Adds better debugging output. Also adds a return; to free :P
This commit is contained in:
parent
2faadc29e9
commit
d55ff69193
17 changed files with 175 additions and 82 deletions
7
Makefile
7
Makefile
|
@ -40,7 +40,7 @@ obj/console.o: src/console.c include/console.h include/stdlib.h \
|
|||
# src/init.c
|
||||
obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \
|
||||
include/console.h include/interrupts.h include/cpustate.h include/pmm.h \
|
||||
include/multiboot.h include/vmm.h include/timer.h
|
||||
include/multiboot.h include/vmm.h include/config.h include/timer.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/init.c
|
||||
|
||||
# src/interrupts.c
|
||||
|
@ -69,8 +69,9 @@ obj/timer.o: src/timer.c include/timer.h include/kernel.h \
|
|||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/timer.c
|
||||
|
||||
# src/vmm.c
|
||||
obj/vmm.o: src/vmm.c include/vmm.h include/pmm.h include/multiboot.h \
|
||||
include/stdlib.h include/varargs.h include/console.h include/kernel.h
|
||||
obj/vmm.o: src/vmm.c include/config.h include/vmm.h include/pmm.h \
|
||||
include/multiboot.h include/stdlib.h include/varargs.h include/console.h \
|
||||
include/kernel.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/vmm.c
|
||||
|
||||
# trainscript/tsvm.cpp
|
||||
|
|
5
include/config.h
Normal file
5
include/config.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
#define USE_VIRTUAL_MEMORY_MANAGEMENT
|
||||
//*/
|
|
@ -46,12 +46,6 @@ namespace ker
|
|||
this->copyFrom(bytes, length);
|
||||
}
|
||||
|
||||
String & operator = (const String &other)
|
||||
{
|
||||
this->copyFrom(other.mText, other.mLength);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
if(this->mText != nullptr) {
|
||||
|
@ -82,11 +76,6 @@ namespace ker
|
|||
return cat;
|
||||
}
|
||||
|
||||
static String concat(const String &lhs, const String &rhs)
|
||||
{
|
||||
return lhs.append(rhs);
|
||||
}
|
||||
|
||||
const uint8_t *text() const
|
||||
{
|
||||
static const uint8_t empty[] = { 0 };
|
||||
|
@ -122,6 +111,12 @@ namespace ker
|
|||
return this->mText[index];
|
||||
}
|
||||
|
||||
String & operator = (const String &other)
|
||||
{
|
||||
this->copyFrom(other.mText, other.mLength);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const String &other) const
|
||||
{
|
||||
return this->equals(other);
|
||||
|
@ -131,6 +126,12 @@ namespace ker
|
|||
{
|
||||
return !this->equals(other);
|
||||
}
|
||||
|
||||
String operator +(const String &other) const
|
||||
{
|
||||
return this->append(other);
|
||||
}
|
||||
|
||||
private:
|
||||
void copyFrom(const uint8_t *bytes, size_t length)
|
||||
{
|
||||
|
@ -142,6 +143,18 @@ namespace ker
|
|||
this->mLength = length;
|
||||
this->mText[this->mLength] = 0; // last byte is always 0
|
||||
}
|
||||
public:
|
||||
static String concat(const String &lhs, const String &rhs)
|
||||
{
|
||||
return lhs.append(rhs);
|
||||
}
|
||||
|
||||
static String fromNumber(int32_t number, int radix = 10)
|
||||
{
|
||||
static char buffer[64];
|
||||
itoa(number, buffer, radix);
|
||||
return String(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ extern "C" {
|
|||
|
||||
void die(const char *msg);
|
||||
|
||||
void die_extra(const char *msg, const char *extra);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -95,6 +95,28 @@ static inline size_t strlen(const char *str)
|
|||
return size;
|
||||
}
|
||||
|
||||
static inline int strcmp(const char *p1, const char *p2)
|
||||
{
|
||||
while(*p1) {
|
||||
if(*p2 == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(*p2 > *p1) {
|
||||
return -1;
|
||||
}
|
||||
if(*p1 > *p2) {
|
||||
return 1;
|
||||
}
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
if (*p2) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void *calloc(size_t size)
|
||||
{
|
||||
void *mem = malloc(size);
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(USE_VIRTUAL_MEMORY_MANAGEMENT)
|
||||
|
||||
#define VM_PRESENT 0x01
|
||||
#define VM_WRITABLE 0x02
|
||||
#define VM_USER 0x04
|
||||
|
@ -24,6 +27,8 @@ void vmm_init(void);
|
|||
*/
|
||||
void vmm_map(uintptr_t virtual, uintptr_t physical, uint32_t flags);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,11 +3,10 @@ VAR global : INT;
|
|||
PUB main() | i : INT
|
||||
BEGIN
|
||||
0 -> i;
|
||||
# Print numbers from 1 to 5
|
||||
WHILE ((i + 1) -> i) <= 5 DO
|
||||
WHILE ((i + 1) -> i) <= 50 DO
|
||||
BEGIN
|
||||
printInt(i);
|
||||
sleep(20);
|
||||
sleep(2);
|
||||
END
|
||||
END
|
||||
|
||||
|
|
40
src/init.c
40
src/init.c
|
@ -4,18 +4,28 @@
|
|||
#include <interrupts.h>
|
||||
#include <pmm.h>
|
||||
#include <vmm.h>
|
||||
|
||||
#include <timer.h>
|
||||
#include <config.h>
|
||||
|
||||
void die(const char *msg)
|
||||
{
|
||||
kputs("\n");
|
||||
ksetcolor(COLOR_RED, COLOR_WHITE);
|
||||
kputs(msg);
|
||||
while(1)
|
||||
{
|
||||
__asm__ volatile ("cli; hlt;");
|
||||
}
|
||||
die_extra(msg, "");
|
||||
}
|
||||
|
||||
void die_extra(const char *msg, const char *extra)
|
||||
{
|
||||
kputs("\n");
|
||||
ksetcolor(COLOR_RED, COLOR_WHITE);
|
||||
kputs(msg);
|
||||
if((extra != nullptr) && (strlen(extra) > 0)) {
|
||||
kputs(": '");
|
||||
kputs(extra);
|
||||
kputc('\'');
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
__asm__ volatile ("cli; hlt;");
|
||||
}
|
||||
}
|
||||
|
||||
extern size_t mallocCount;
|
||||
|
@ -156,12 +166,14 @@ void init(const MultibootStructure *mbHeader)
|
|||
pmm_init(mbHeader);
|
||||
putsuccess();
|
||||
|
||||
// uint32_t freeMem = pmm_calc_free();
|
||||
//kprintf("Free memory: %d B, %d kB, %d MB\n", freeMem, freeMem >> 10, freeMem >> 20);
|
||||
uint32_t freeMem = pmm_calc_free();
|
||||
kprintf("Free memory: %d B, %d kB, %d MB\n", freeMem, freeMem >> 10, freeMem >> 20);
|
||||
|
||||
kputs("Initialize virtual memory management: ");
|
||||
#if defined(USE_VIRTUAL_MEMORY_MANAGEMENT)
|
||||
kputs("Initialize virtual memory management: ");
|
||||
vmm_init();
|
||||
putsuccess();
|
||||
#endif
|
||||
|
||||
kputs("Initialize interrupts:");
|
||||
intr_init();
|
||||
|
@ -171,12 +183,14 @@ void init(const MultibootStructure *mbHeader)
|
|||
irq_enable();
|
||||
putsuccess();
|
||||
|
||||
#if defined(USE_VIRTUAL_MEMORY_MANAGEMENT)
|
||||
kputs("Prepare heap memory:");
|
||||
for(uintptr_t ptr = 0x400000; ptr < 0x800000; ptr += 4096)
|
||||
for(uintptr_t ptr = 0x400000; ptr < 0x800000; ptr += 4096)
|
||||
{
|
||||
vmm_map(ptr, (uintptr_t)pmm_alloc(), VM_PROGRAM);
|
||||
}
|
||||
putsuccess();
|
||||
#endif
|
||||
|
||||
kputs("Initialize timer:");
|
||||
timer_init();
|
||||
|
@ -188,8 +202,6 @@ void init(const MultibootStructure *mbHeader)
|
|||
|
||||
timer_add_callback(1, update_statusbar);
|
||||
|
||||
debug_test();
|
||||
|
||||
vm_start();
|
||||
|
||||
kputs("\x12\x04trainOS stopped.\x12\x07!\n");
|
||||
|
|
|
@ -173,7 +173,10 @@ void *malloc(size_t len)
|
|||
|
||||
void free(void *p)
|
||||
{
|
||||
freeCount++;
|
||||
freeCount++;
|
||||
|
||||
return;
|
||||
|
||||
struct __freelist *fp1, *fp2, *fpnew;
|
||||
char *cp1, *cp2, *cpnew;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
case TypeID::Bool: stackSize += sizeof(Int); break;
|
||||
case TypeID::Int: stackSize += sizeof(Int); break;
|
||||
case TypeID::Real: stackSize += sizeof(Real); break;
|
||||
default: die("invalid argument type."); break;
|
||||
default: die_extra("NativeMethod.InvalidArgument", arguments[i].type.name()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,6 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
*reinterpret_cast<Real*>(stack) = arguments[i].real;
|
||||
stack += sizeof(Real);
|
||||
break;
|
||||
default: die("invalid argument type."); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
src/vmm.c
15
src/vmm.c
|
@ -1,8 +1,11 @@
|
|||
#include "vmm.h"
|
||||
#include "pmm.h"
|
||||
#include "stdlib.h"
|
||||
#include "console.h"
|
||||
#include "kernel.h"
|
||||
#include <config.h>
|
||||
#include <vmm.h>
|
||||
#include <pmm.h>
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
#include <kernel.h>
|
||||
|
||||
#if defined(USE_VIRTUAL_MEMORY_MANAGEMENT)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -79,3 +82,5 @@ void vmm_init(void)
|
|||
cr0 |= (1 << 31);
|
||||
__asm__ volatile("mov %0, %%cr0" : : "r" (cr0));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,8 @@ HEADERS += \
|
|||
include/ker/dictionary.hpp \
|
||||
include/string.h \
|
||||
include/ker/new.hpp \
|
||||
include/dynamic.h
|
||||
include/dynamic.h \
|
||||
include/config.h
|
||||
|
||||
DISTFILES += \
|
||||
asm/intr_common_handler.S \
|
||||
|
|
|
@ -21,14 +21,29 @@ void yyerror(void *scanner, const char *s);
|
|||
} \
|
||||
}
|
||||
|
||||
typedef struct
|
||||
struct ParserData
|
||||
{
|
||||
char *buffer;
|
||||
size_t index;
|
||||
size_t length;
|
||||
trainscript::Module *module;
|
||||
void *scanner;
|
||||
} ParserData;
|
||||
char* strings[256];
|
||||
|
||||
char *strdup(const char *str)
|
||||
{
|
||||
for(size_t i = 0; i < 256; i++) {
|
||||
if(this->strings[i] == nullptr) {
|
||||
return this->strings[i] = ::strdup(str);
|
||||
}
|
||||
else if(strcmp(this->strings[i], str) == 0) {
|
||||
return this->strings[i];
|
||||
}
|
||||
}
|
||||
die_extra("ParserData::strdup", "out of strings");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct VariableDeclaration
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ WHILE { return KW_WHILE; }
|
|||
DO { return KW_DO; }
|
||||
[0-9]+\.[0-9]* { yylval->fval = atof(yytext); return REAL; }
|
||||
[0-9]+ { yylval->ival = atoi(yytext); return INT; }
|
||||
[a-zA-Z0-9'_]+ { yylval->text = strdup(yytext); return IDENTIFIER; }
|
||||
[a-zA-Z0-9'_]+ { yylval->text = yyextra->strdup(yytext); return IDENTIFIER; }
|
||||
. { yyerror(NULL, "illegal token"); }
|
||||
%%
|
||||
/*
|
||||
|
|
|
@ -58,6 +58,12 @@ namespace trainscript
|
|||
yylex_destroy(data.scanner);
|
||||
free(internalStorage);
|
||||
|
||||
for(size_t i = 0; i < 256; i++) {
|
||||
if(data.strings[i] != nullptr) {
|
||||
free(data.strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(valid) {
|
||||
return module;
|
||||
} else {
|
||||
|
@ -104,11 +110,11 @@ namespace trainscript
|
|||
context.add(this->mReturnValue.first, &returnVariable);
|
||||
}
|
||||
if(arguments.length() != this->mArguments.length()) {
|
||||
return Variable::Invalid;
|
||||
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) {
|
||||
return Variable::Invalid;
|
||||
die_extra("ScriptMethod::invoke", "Invalid argument type.");
|
||||
}
|
||||
context.add(this->mArguments[i].first, new Variable(arguments[i]));
|
||||
}
|
||||
|
@ -176,7 +182,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id)); return Variable::Invalid;
|
||||
default: kprintf("addition not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +191,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id)); return Variable::Invalid;
|
||||
default: kprintf("subtraction not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +200,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id)); return Variable::Invalid;
|
||||
default: kprintf("multiplication not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +209,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id)); return Variable::Invalid;
|
||||
default: kprintf("division not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,7 +218,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id)); return Variable::Invalid;
|
||||
default: kprintf("modulo not supported for %s.\n", lhs.type.name()); return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +229,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +241,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("inequals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +253,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +264,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +275,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +286,7 @@ namespace trainscript
|
|||
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", typeName(lhs.type.id));
|
||||
kprintf("equals not supported for %s.\n", lhs.type.name());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,18 @@ namespace trainscript
|
|||
(this->pointer != other.pointer);
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
static const Type Invalid;
|
||||
static const Type Void;
|
||||
static const Type Int;
|
||||
|
@ -288,7 +300,7 @@ namespace trainscript
|
|||
Variable execute(LocalContext &context) const override {
|
||||
auto *var = context.get(this->variableName);
|
||||
if(var == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die_extra("VariableExpression.VariableNotFound", this->variableName.str());
|
||||
}
|
||||
return *var;
|
||||
}
|
||||
|
@ -328,17 +340,17 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->expression == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die("VariableAssignmentExpression.ExpressionMissing");
|
||||
}
|
||||
Variable result = this->expression->execute(context);
|
||||
|
||||
Variable *target = context.get(this->variableName);
|
||||
if(target == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die_extra("VariableAssignmentExpression.VariableNotFound", this->variableName.str());
|
||||
}
|
||||
|
||||
if(target->type != result.type) {
|
||||
return Variable::Invalid;
|
||||
die_extra("VariableAssignmentExpression.ExpectedType", result.type.name());
|
||||
}
|
||||
|
||||
switch(target->type.id) {
|
||||
|
@ -406,7 +418,7 @@ namespace trainscript
|
|||
{
|
||||
Method *method = context.module->method(this->methodName.str());
|
||||
if(method == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die_extra("MethodInvokeExpression.MethodNotFound", this->methodName.str());
|
||||
}
|
||||
|
||||
ker::Vector<Variable> vars(this->parameters.length());
|
||||
|
@ -467,20 +479,25 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->lhs == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die_extra("ArithmeticExpression.ExpressionMissing", "Left-hand side");
|
||||
}
|
||||
if(this->rhs == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die_extra("ArithmeticExpression.ExpressionMissing", "Right-hand side");
|
||||
}
|
||||
|
||||
Variable left = this->lhs->execute(context);
|
||||
Variable right = this->rhs->execute(context);
|
||||
|
||||
if(left.type != right.type) {
|
||||
return Variable::Invalid;
|
||||
die("ArithmeticExpression.TypeMismatch");
|
||||
}
|
||||
|
||||
return OP(left, right);
|
||||
Variable result = OP(left, right);
|
||||
|
||||
if(result.type.usable() == false) {
|
||||
die_extra("ArithmeticExpression.InvalidResult", result.type.name());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool validate(LocalContext &context, ker::String &errorCode) const override {
|
||||
|
@ -543,12 +560,12 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->condition == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die("IfExpression.ConditionMissing");
|
||||
}
|
||||
|
||||
Variable result = this->condition->execute(context);
|
||||
if(result.type != Type::Boolean) {
|
||||
return Variable::Invalid;
|
||||
die_extra("IfExpression.TypeMismatch", result.type.name());
|
||||
}
|
||||
if((result.boolean == true) && (this->blockTrue != nullptr)) {
|
||||
this->blockTrue->execute(context);
|
||||
|
@ -574,7 +591,7 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->block == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die("RepeatEndlessExpression.BlockMissing");
|
||||
}
|
||||
|
||||
while(true)
|
||||
|
@ -603,10 +620,10 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->condition == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die("RepeatWhileExpression.ConditionMissing");
|
||||
}
|
||||
if(this->block == nullptr) {
|
||||
return Variable::Invalid;
|
||||
die("RepeatWhileExpression.BlockMissing");
|
||||
}
|
||||
|
||||
while(true)
|
||||
|
|
|
@ -11,16 +11,4 @@ namespace trainscript
|
|||
Text = 4,
|
||||
Bool = 5,
|
||||
};
|
||||
|
||||
static const char *typeName(TypeID id) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue