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