some stuff.
This commit is contained in:
parent
cf02215de8
commit
ddbfb0e1aa
32 changed files with 922 additions and 202 deletions
28
Makefile
28
Makefile
|
@ -1,16 +1,20 @@
|
||||||
SRCS = $(shell find -name '*.[cS]')
|
SRCS = $(shell find . -regextype posix-egrep -regex '.*\.[cS]') src/cplusplus.cpp
|
||||||
OBJS = $(addsuffix .o,$(basename $(SRCS)))
|
OBJS = $(addsuffix .o,$(basename $(SRCS)))
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
CXX = g++
|
||||||
LD = ld
|
LD = ld
|
||||||
|
LEX=flex
|
||||||
|
YACC=bison
|
||||||
|
|
||||||
# define nullptr, but not NULL.
|
# define nullptr, but not NULL.
|
||||||
CFLAGS = -m32 -Dnullptr=0
|
CFLAGS = -m32 -Dnullptr=0
|
||||||
ASFLAGS =
|
ASFLAGS =
|
||||||
CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding
|
CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding -Iinclude
|
||||||
|
CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-exceptions -ffreestanding -Wno-unused-function -Iinclude
|
||||||
LDFLAGS = -g -melf_i386 -Tkernel.ld
|
LDFLAGS = -g -melf_i386 -Tkernel.ld
|
||||||
|
|
||||||
kernel: $(OBJS)
|
kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o
|
||||||
$(LD) $(LDFLAGS) -o $@ $(addprefix obj/, $(notdir $^))
|
$(LD) $(LDFLAGS) -o $@ $(addprefix obj/, $(notdir $^))
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
|
@ -19,6 +23,24 @@ kernel: $(OBJS)
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS) $(ASFLAGS) -c -o $(addprefix obj/, $(notdir $@)) $^
|
$(CC) $(CFLAGS) $(ASFLAGS) -c -o $(addprefix obj/, $(notdir $@)) $^
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $(addprefix obj/, $(notdir $@)) $^
|
||||||
|
|
||||||
|
obj/tsvm.o: trainscript/tsvm.cpp trainscript/tsvm.hpp trainscript/common.h
|
||||||
|
g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/tsvm.cpp -o obj/tsvm.o
|
||||||
|
|
||||||
|
obj/lex.yy.o: trainscript/lex.yy.cpp trainscript/tsvm.hpp trainscript/common.h trainscript/trainscript.tab.cpp
|
||||||
|
g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/lex.yy.cpp -o obj/lex.yy.o
|
||||||
|
|
||||||
|
trainscript.tab.o: trainscript/lex.yy.cpp trainscript/trainscript.tab.cpp trainscript/tsvm.hpp trainscript/common.h
|
||||||
|
g++ $(CFLAGS) $(CXXFLAGS) -c trainscript/trainscript.tab.cpp -o obj/trainscript.tab.o
|
||||||
|
|
||||||
|
trainscript/lex.yy.cpp: trainscript/trainscript.l
|
||||||
|
$(LEX) --header-file=trainscript/trainscript.l.h -o trainscript/lex.yy.cpp trainscript/trainscript.l
|
||||||
|
|
||||||
|
trainscript/trainscript.tab.cpp: trainscript/trainscript.y
|
||||||
|
$(YACC) -o trainscript/trainscript.tab.cpp -d trainscript/trainscript.y
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm $(addprefix obj/, $(notdir $(OBJS)))
|
rm $(addprefix obj/, $(notdir $(OBJS)))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CONSOLE_WIDTH 80
|
#define CONSOLE_WIDTH 80
|
||||||
#define CONSOLE_HEIGHT 25
|
#define CONSOLE_HEIGHT 25
|
||||||
|
|
||||||
|
@ -71,4 +75,8 @@ void kputs(const char *str);
|
||||||
* @param format The format string that will be printed in formatted version.
|
* @param format The format string that will be printed in formatted version.
|
||||||
* @param ... The format parameters that will be used to print the string.
|
* @param ... The format parameters that will be used to print the string.
|
||||||
*/
|
*/
|
||||||
void kprintf(const char *format, ...);
|
void kprintf(const char *format, ...);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// Saved by interrupt routine
|
// Saved by interrupt routine
|
||||||
|
@ -21,4 +25,8 @@ typedef struct
|
||||||
uint32_t eflags;
|
uint32_t eflags;
|
||||||
uint32_t esp;
|
uint32_t esp;
|
||||||
uint32_t ss;
|
uint32_t ss;
|
||||||
} CpuState;
|
} CpuState;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,4 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "cpustate.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GDTF_DATASEG 0x02
|
#define GDTF_DATASEG 0x02
|
||||||
#define GDTF_CODESEG 0x0a
|
#define GDTF_CODESEG 0x0a
|
||||||
|
@ -16,11 +21,20 @@
|
||||||
#define INTR_TRAP_GATE 7
|
#define INTR_TRAP_GATE 7
|
||||||
#define INTR_TASK_GATE 5
|
#define INTR_TASK_GATE 5
|
||||||
|
|
||||||
|
typedef void (*InterruptHandler)(CpuState *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes interrupt handling and the global descriptor table.
|
* Initializes interrupt handling and the global descriptor table.
|
||||||
*/
|
*/
|
||||||
void intr_init();
|
void intr_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the handler for the given interrupt.
|
||||||
|
* @param interrupt The number of the interrupt.
|
||||||
|
* @param handler The function that should handle this interrupt
|
||||||
|
*/
|
||||||
|
void intr_set_handler(uint32_t interrupt, InterruptHandler handler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables physical interrupts.
|
* @brief Enables physical interrupts.
|
||||||
*/
|
*/
|
||||||
|
@ -37,3 +51,6 @@ static inline void irq_disable(void)
|
||||||
__asm__ volatile("cli");
|
__asm__ volatile("cli");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "inttypes.h"
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Outputs a byte on the given port.
|
* @brief Outputs a byte on the given port.
|
||||||
|
@ -11,3 +16,7 @@ static inline void outb(uint16_t port, uint8_t data)
|
||||||
{
|
{
|
||||||
__asm__ volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
|
__asm__ volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
98
include/ker/dictionary.hpp
Normal file
98
include/ker/dictionary.hpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pair.hpp"
|
||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
|
namespace ker
|
||||||
|
{
|
||||||
|
template<typename Key, typename Value>
|
||||||
|
class Dictionary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Pair<Key, Value> Entry;
|
||||||
|
private:
|
||||||
|
Vector<Entry> contents;
|
||||||
|
public:
|
||||||
|
Dictionary() :
|
||||||
|
contents()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Value &at(const Key &key)
|
||||||
|
{
|
||||||
|
for(auto &&pair : this->contents)
|
||||||
|
{
|
||||||
|
if(pair.first == key) {
|
||||||
|
return pair.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value &at(const Key &key) const
|
||||||
|
{
|
||||||
|
for(auto &&pair : this->contents)
|
||||||
|
{
|
||||||
|
if(pair.first == key) {
|
||||||
|
return pair.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const Key &key) const
|
||||||
|
{
|
||||||
|
for(const auto &pair : this->contents)
|
||||||
|
{
|
||||||
|
if(pair.first == key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const Key &key, const Value &value)
|
||||||
|
{
|
||||||
|
if(this->contains(key)) {
|
||||||
|
for(auto &&pair : this->contents)
|
||||||
|
{
|
||||||
|
if(pair.first == key) {
|
||||||
|
pair.second = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->contents.append(Entry(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value& operator [](const Key &key)
|
||||||
|
{
|
||||||
|
return this->at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value& operator [](const Key &key) const
|
||||||
|
{
|
||||||
|
return this->at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry * begin()
|
||||||
|
{
|
||||||
|
return this->contents.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry * end()
|
||||||
|
{
|
||||||
|
return this->contents.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Entry * begin() const
|
||||||
|
{
|
||||||
|
return this->contents.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Entry * end() const
|
||||||
|
{
|
||||||
|
return this->contents.end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
16
include/ker/new.hpp
Normal file
16
include/ker/new.hpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
inline void* operator new(size_t size, void* __p)
|
||||||
|
{
|
||||||
|
return __p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* operator new[](size_t size, void* __p)
|
||||||
|
{
|
||||||
|
return __p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void operator delete (void*, void*) { }
|
||||||
|
inline void operator delete[](void*, void*) { }
|
20
include/ker/pair.hpp
Normal file
20
include/ker/pair.hpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ker
|
||||||
|
{
|
||||||
|
template<typename First, typename Second>
|
||||||
|
struct Pair
|
||||||
|
{
|
||||||
|
First first;
|
||||||
|
Second second;
|
||||||
|
|
||||||
|
Pair() : first(), second() { }
|
||||||
|
|
||||||
|
Pair(const First &first, const Second &second) :
|
||||||
|
first(first),
|
||||||
|
second(second)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
100
include/ker/string.hpp
Normal file
100
include/ker/string.hpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
namespace ker
|
||||||
|
{
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t *mText;
|
||||||
|
size_t mLength;
|
||||||
|
public:
|
||||||
|
String() :
|
||||||
|
mText(nullptr),
|
||||||
|
mLength(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const char *text) :
|
||||||
|
mText(nullptr),
|
||||||
|
mLength(0)
|
||||||
|
{
|
||||||
|
this->mLength = strlen(text);
|
||||||
|
this->mText = (uint8_t*)malloc(this->mLength + 1);
|
||||||
|
memcpy(this->mText, text, this->mLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const uint8_t *bytes, size_t length) :
|
||||||
|
mText((uint8_t*)malloc(length)),
|
||||||
|
mLength(length)
|
||||||
|
{
|
||||||
|
memcpy(this->mText, bytes, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
free(this->mText);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length() const
|
||||||
|
{
|
||||||
|
return this->mLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equals(const String &other) const
|
||||||
|
{
|
||||||
|
if(this->mLength != other.mLength) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return memcmp(this->mText, other.mText, this->mLength) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *text() const
|
||||||
|
{
|
||||||
|
static const uint8_t empty[] = { 0 };
|
||||||
|
if(this->mText != nullptr) {
|
||||||
|
return this->mText;
|
||||||
|
} else {
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *str() const
|
||||||
|
{
|
||||||
|
return (char*)this->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const uint8_t *() const
|
||||||
|
{
|
||||||
|
return this->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const char *() const
|
||||||
|
{
|
||||||
|
return this->str();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t & operator [](size_t index)
|
||||||
|
{
|
||||||
|
return this->mText[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t & operator [](size_t index) const
|
||||||
|
{
|
||||||
|
return this->mText[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(const String &other) const
|
||||||
|
{
|
||||||
|
return this->equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !=(const String &other) const
|
||||||
|
{
|
||||||
|
return !this->equals(other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
117
include/ker/vector.hpp
Normal file
117
include/ker/vector.hpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "new.hpp"
|
||||||
|
|
||||||
|
namespace ker
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class Vector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const size_t initialCap = 32;
|
||||||
|
private:
|
||||||
|
T *mData;
|
||||||
|
size_t mLength;
|
||||||
|
size_t mReserved;
|
||||||
|
public:
|
||||||
|
Vector() :
|
||||||
|
mData(nullptr),
|
||||||
|
mLength(0),
|
||||||
|
mReserved(0)
|
||||||
|
{
|
||||||
|
this->reserve(Vector<T>::initialCap);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit Vector(size_t initialReserve) :
|
||||||
|
Vector()
|
||||||
|
{
|
||||||
|
this->reserve(initialReserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length() const
|
||||||
|
{
|
||||||
|
return this->mLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &at(size_t index)
|
||||||
|
{
|
||||||
|
return this->mData[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &at(size_t index) const
|
||||||
|
{
|
||||||
|
return this->mData[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const T &value)
|
||||||
|
{
|
||||||
|
this->reserve(this->mLength + 1);
|
||||||
|
new (&this->mData[this->mLength - 1]) T(value);
|
||||||
|
this->mLength += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
size_t current = this->mLength;
|
||||||
|
this->reserve(size);
|
||||||
|
|
||||||
|
if(current > size) {
|
||||||
|
// "Downgrade"
|
||||||
|
for(size_t i = this->mLength - 1; i > size; i--) {
|
||||||
|
this->mData[i].~T();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// "Upgrade"
|
||||||
|
for(size_t i = this->mLength; i < size; i++) {
|
||||||
|
new (&this->mData[i]) T ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t space)
|
||||||
|
{
|
||||||
|
if(this->mReserved >= space) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size_t newSize = sizeof(T) * space;
|
||||||
|
|
||||||
|
T *newData = (T*)malloc(newSize);
|
||||||
|
if(this->mData != nullptr) {
|
||||||
|
memcpy(newData, this->mData, newSize);
|
||||||
|
free(this->mData);
|
||||||
|
}
|
||||||
|
this->mData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator [](size_t idx)
|
||||||
|
{
|
||||||
|
return this->at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator [](size_t idx) const
|
||||||
|
{
|
||||||
|
return this->at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* begin()
|
||||||
|
{
|
||||||
|
return &this->mData[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
T* end()
|
||||||
|
{
|
||||||
|
return &this->mData[this->mLength];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* begin() const
|
||||||
|
{
|
||||||
|
return &this->mData[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* end() const
|
||||||
|
{
|
||||||
|
return &this->mData[this->mLength];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
13
include/kernel.h
Normal file
13
include/kernel.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void die(const char *msg);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MB_MEMSIZE (1<<0)
|
#define MB_MEMSIZE (1<<0)
|
||||||
#define MB_BOOTDEVICE (1<<1)
|
#define MB_BOOTDEVICE (1<<1)
|
||||||
#define MB_COMMANDLINE (1<<2)
|
#define MB_COMMANDLINE (1<<2)
|
||||||
|
@ -89,3 +93,7 @@ typedef struct {
|
||||||
uint16_t vbeInterfaceOffset;
|
uint16_t vbeInterfaceOffset;
|
||||||
uint16_t vbeInterfaceLength;
|
uint16_t vbeInterfaceLength;
|
||||||
} __attribute__((packed)) MultibootStructure;
|
} __attribute__((packed)) MultibootStructure;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes physical memory management.
|
* Initializes physical memory management.
|
||||||
* @param mb The multi boot structure used for gathering information about free memory.
|
* @param mb The multi boot structure used for gathering information about free memory.
|
||||||
|
@ -22,3 +26,7 @@ void *pmm_alloc(void);
|
||||||
* Calculates the free memory in bytes.
|
* Calculates the free memory in bytes.
|
||||||
*/
|
*/
|
||||||
uint32_t pmm_calc_free(void);
|
uint32_t pmm_calc_free(void);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -4,6 +4,10 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "varargs.h"
|
#include "varargs.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
char *itoa(int value, char *str, int base);
|
char *itoa(int value, char *str, int base);
|
||||||
int atoi(const char *str);
|
int atoi(const char *str);
|
||||||
float atof(const char *str);
|
float atof(const char *str);
|
||||||
|
@ -21,6 +25,10 @@ void *malloc(size_t size);
|
||||||
*/
|
*/
|
||||||
void free(void *mem);
|
void free(void *mem);
|
||||||
|
|
||||||
|
void* realloc (void* ptr, size_t size);
|
||||||
|
|
||||||
|
void exit(int errorCode);
|
||||||
|
|
||||||
static inline void *memset(void *ptr, int value, size_t num)
|
static inline void *memset(void *ptr, int value, size_t num)
|
||||||
{
|
{
|
||||||
uint8_t *it = (uint8_t*)ptr;
|
uint8_t *it = (uint8_t*)ptr;
|
||||||
|
@ -44,6 +52,20 @@ static inline void *memcpy(void *destination, const void *source, size_t num)
|
||||||
|
|
||||||
void *memmove(void *destination, const void *source, size_t num);
|
void *memmove(void *destination, const void *source, size_t num);
|
||||||
|
|
||||||
|
static inline int memcmp(const void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
const uint8_t * p1 = (const uint8_t *)s1;
|
||||||
|
const uint8_t * p2 = (const uint8_t *)s2;
|
||||||
|
for ( ; n-- ; p1++, p2++) {
|
||||||
|
uint8_t u1 = *p1;
|
||||||
|
uint8_t u2 = *p2;
|
||||||
|
if ( u1 != u2) {
|
||||||
|
return (u1-u2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline char *strcpy(char *destination, const char *source)
|
static inline char *strcpy(char *destination, const char *source)
|
||||||
{
|
{
|
||||||
while(*source)
|
while(*source)
|
||||||
|
@ -79,3 +101,15 @@ static inline void *calloc(size_t size)
|
||||||
memset(mem, 0, size);
|
memset(mem, 0, size);
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char * strdup(const char *str)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str) + 1;
|
||||||
|
char * n = (char*)malloc(len);
|
||||||
|
memcpy(n, str, len);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
3
include/string.h
Normal file
3
include/string.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdlib.h"
|
35
include/timer.h
Normal file
35
include/timer.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the hardware timer.
|
||||||
|
*/
|
||||||
|
void timer_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the number of ticks the timer has ticked.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint64_t timer_get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the timer to a given value.
|
||||||
|
* @param time The number of ticks the timer should have now.
|
||||||
|
*/
|
||||||
|
void timer_set(uint64_t time);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits until a certain time elapsed.
|
||||||
|
* @param ticks The number of ticks to wait
|
||||||
|
*/
|
||||||
|
void sleep(uint64_t ticks);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef __builtin_va_list va_list;
|
typedef __builtin_va_list va_list;
|
||||||
#define va_start(ap, X) __builtin_va_start(ap, X)
|
#define va_start(ap, X) __builtin_va_start(ap, X)
|
||||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||||
#define va_end(ap) __builtin_va_end(ap)
|
#define va_end(ap) __builtin_va_end(ap)
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VM_PRESENT 0x01
|
#define VM_PRESENT 0x01
|
||||||
#define VM_WRITABLE 0x02
|
#define VM_WRITABLE 0x02
|
||||||
#define VM_USER 0x04
|
#define VM_USER 0x04
|
||||||
|
@ -19,3 +23,7 @@ void vmm_init(void);
|
||||||
* @remarks If flags is 0, the mapping will be undone.
|
* @remarks If flags is 0, the mapping will be undone.
|
||||||
*/
|
*/
|
||||||
void vmm_map(uintptr_t virtual, uintptr_t physical, uint32_t flags);
|
void vmm_map(uintptr_t virtual, uintptr_t physical, uint32_t flags);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
24
src/cplusplus.cpp
Normal file
24
src/cplusplus.cpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <ker/new.hpp>
|
||||||
|
|
||||||
|
void *operator new( size_t size )
|
||||||
|
{
|
||||||
|
return calloc( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new[]( size_t size )
|
||||||
|
{
|
||||||
|
return calloc( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete( void *obj )
|
||||||
|
{
|
||||||
|
free( obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete[]( void *obj )
|
||||||
|
{
|
||||||
|
free( obj );
|
||||||
|
}
|
76
src/init.c
76
src/init.c
|
@ -1,9 +1,11 @@
|
||||||
#include "kernel.h"
|
#include <kernel.h>
|
||||||
#include "stdlib.h"
|
#include <stdlib.h>
|
||||||
#include "console.h"
|
#include <console.h>
|
||||||
#include "interrupts.h"
|
#include <interrupts.h>
|
||||||
#include "pmm.h"
|
#include <pmm.h>
|
||||||
#include "vmm.h"
|
#include <vmm.h>
|
||||||
|
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
void die(const char *msg)
|
void die(const char *msg)
|
||||||
{
|
{
|
||||||
|
@ -16,15 +18,6 @@ void die(const char *msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksleep(uint32_t time)
|
|
||||||
{
|
|
||||||
for(uint32_t i = 0; i < time; i++)
|
|
||||||
{
|
|
||||||
// BURN, CPU, BURN!
|
|
||||||
for(volatile size_t i = 0; i < 40000000; i++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_test()
|
static void debug_test()
|
||||||
{
|
{
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
@ -101,6 +94,18 @@ static void dumpMB(const MultibootStructure *mbHeader)
|
||||||
// TODO: MB_APS_TABLE
|
// TODO: MB_APS_TABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpp_init()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void putsuccess()
|
||||||
|
{
|
||||||
|
int y; kgetpos(nullptr, &y);
|
||||||
|
ksetpos(CONSOLE_WIDTH - 9, y);
|
||||||
|
kputs("[success]");
|
||||||
|
}
|
||||||
|
|
||||||
void init(const MultibootStructure *mbHeader)
|
void init(const MultibootStructure *mbHeader)
|
||||||
{
|
{
|
||||||
(void)debug_test;
|
(void)debug_test;
|
||||||
|
@ -113,37 +118,42 @@ void init(const MultibootStructure *mbHeader)
|
||||||
//dumpMB(mbHeader);
|
//dumpMB(mbHeader);
|
||||||
|
|
||||||
kputs("Initialize physical memory management: ");
|
kputs("Initialize physical memory management: ");
|
||||||
pmm_init(mbHeader);
|
pmm_init(mbHeader);
|
||||||
kputs("success.\n");
|
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);
|
||||||
|
|
||||||
ksleep(1);
|
|
||||||
|
|
||||||
kputs("Initialize virtual memory management: ");
|
kputs("Initialize virtual memory management: ");
|
||||||
vmm_init();
|
vmm_init();
|
||||||
kputs("success.\n");
|
putsuccess();
|
||||||
|
|
||||||
kputs("Initialize interrupts: ");
|
kputs("Initialize interrupts:");
|
||||||
intr_init();
|
intr_init();
|
||||||
kputs("success.\n");
|
putsuccess();
|
||||||
|
|
||||||
kputs("Enable hw interrupts: ");
|
kputs("Enable hw interrupts:");
|
||||||
irq_enable();
|
irq_enable();
|
||||||
kputs("success.\n");
|
putsuccess();
|
||||||
|
|
||||||
//__asm__ volatile("sti");
|
kputs("Prepare heap memory:");
|
||||||
|
for(uintptr_t ptr = 0x400000; ptr < 0x800000; ptr += 4096)
|
||||||
|
{
|
||||||
|
vmm_map(ptr, (uintptr_t)pmm_alloc(), VM_PROGRAM);
|
||||||
|
}
|
||||||
|
putsuccess();
|
||||||
|
|
||||||
kputs("Prepare heap memory: ");
|
kputs("Initialize timer:");
|
||||||
for(uintptr_t ptr = 0x400000; ptr < 0x800000; ptr += 4096)
|
timer_init();
|
||||||
{
|
putsuccess();
|
||||||
vmm_map(ptr, (uintptr_t)pmm_alloc(), VM_PROGRAM);
|
|
||||||
}
|
kputs("Initialize C++ objects: ");
|
||||||
kputs("success.\n");
|
cpp_init();
|
||||||
|
putsuccess();
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
kputs("x");
|
kputs("x");
|
||||||
ksleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
static uint64_t gdt[GDT_ENTRIES];
|
static uint64_t gdt[GDT_ENTRIES];
|
||||||
static uint64_t idt[IDT_ENTRIES];
|
static uint64_t idt[IDT_ENTRIES];
|
||||||
|
|
||||||
|
static InterruptHandler handlers[IDT_ENTRIES];
|
||||||
|
|
||||||
static const char *interruptNames[] = {
|
static const char *interruptNames[] = {
|
||||||
"Divide-by-zero Error",// 0 (0x0) Fault #DE No
|
"Divide-by-zero Error",// 0 (0x0) Fault #DE No
|
||||||
"Debug",// 1 (0x1) Fault/Trap #DB No
|
"Debug",// 1 (0x1) Fault/Trap #DB No
|
||||||
|
@ -65,21 +67,39 @@ static const size_t interruptNameCount = sizeof(interruptNames) / sizeof(interru
|
||||||
|
|
||||||
#include "intr_stubs.h"
|
#include "intr_stubs.h"
|
||||||
|
|
||||||
|
void intr_set_handler(uint32_t interrupt, InterruptHandler handler)
|
||||||
|
{
|
||||||
|
if(interrupt < IDT_ENTRIES) {
|
||||||
|
handlers[interrupt] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void intr_routine(CpuState *state)
|
void intr_routine(CpuState *state)
|
||||||
{
|
{
|
||||||
const char *name = "Unknown";
|
const char *name = "Unknown";
|
||||||
if(state->intr < interruptNameCount)
|
if(state->intr < interruptNameCount)
|
||||||
name = interruptNames[state->intr];
|
name = interruptNames[state->intr];
|
||||||
|
InterruptHandler handler = handlers[state->intr];
|
||||||
if(state->intr < 0x20)
|
if(state->intr < 0x20)
|
||||||
{
|
{
|
||||||
kprintf("\n\x12\x04Exception [%d] %s!\x12\0x7\n", state->intr, name);
|
if(handler != nullptr) {
|
||||||
while(1)
|
handler(state);
|
||||||
{
|
} else {
|
||||||
__asm__ volatile("cli; hlt");
|
kprintf("\n\x12\x04Exception [%d] %s!\x12\0x7\n", state->intr, name);
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
__asm__ volatile("cli; hlt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state->intr >= 0x20 && state->intr <= 0x2f)
|
if (state->intr >= 0x20 && state->intr <= 0x2f)
|
||||||
{
|
{
|
||||||
|
if(handler != nullptr) {
|
||||||
|
handler(state);
|
||||||
|
} else {
|
||||||
|
kprintf("[Unhandled IRQ: %d]", state->intr);
|
||||||
|
}
|
||||||
|
|
||||||
if (state->intr >= 0x28)
|
if (state->intr >= 0x28)
|
||||||
{
|
{
|
||||||
// EOI an Slave-PIC
|
// EOI an Slave-PIC
|
||||||
|
@ -90,11 +110,15 @@ void intr_routine(CpuState *state)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kprintf("\n\x12\x04Interrupt [%d] %s occurred!\x12\0x7\n", state->intr, name);
|
if(handler != nullptr) {
|
||||||
while(1)
|
handler(state);
|
||||||
{
|
} else {
|
||||||
// Prozessor anhalten
|
kprintf("\n\x12\x04Interrupt [%d] %s occurred!\x12\0x7\n", state->intr, name);
|
||||||
__asm__ volatile("cli; hlt");
|
while(1)
|
||||||
|
{
|
||||||
|
// Prozessor anhalten
|
||||||
|
__asm__ volatile("cli; hlt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +264,16 @@ static void init_idt(void)
|
||||||
__asm__ volatile("lidt %0" : : "m" (idtp));
|
__asm__ volatile("lidt %0" : : "m" (idtp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_handlers(void)
|
||||||
|
{
|
||||||
|
memset(handlers, 0, sizeof(handlers));
|
||||||
|
}
|
||||||
|
|
||||||
void intr_init(void)
|
void intr_init(void)
|
||||||
{
|
{
|
||||||
|
// Initialize handler table
|
||||||
|
init_handlers();
|
||||||
|
|
||||||
// Initialize global descriptor table
|
// Initialize global descriptor table
|
||||||
init_gdt();
|
init_gdt();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
void die(const char *msg);
|
|
||||||
|
|
||||||
void ksleep(uint32_t time);
|
|
21
src/stdlib.c
21
src/stdlib.c
|
@ -1,4 +1,23 @@
|
||||||
#include "stdlib.h"
|
#include <stdlib.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
void* realloc (void* ptr, size_t size)
|
||||||
|
{
|
||||||
|
void *n = malloc(size);
|
||||||
|
memcpy(n, ptr, size);
|
||||||
|
free(ptr);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit(int errorCode)
|
||||||
|
{
|
||||||
|
static char buffer[128];
|
||||||
|
static char tmp[10];
|
||||||
|
strcpy(buffer, "Program exited with error code ");
|
||||||
|
strcat(buffer, itoa(errorCode, tmp, 10));
|
||||||
|
strcat(buffer, ".\n");
|
||||||
|
die(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static void reverse(char *str, int length)
|
static void reverse(char *str, int length)
|
||||||
{
|
{
|
||||||
|
|
33
src/timer.c
Normal file
33
src/timer.c
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
|
static volatile uint64_t ticks = 0;
|
||||||
|
|
||||||
|
static void timer_irq()
|
||||||
|
{
|
||||||
|
ticks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_init()
|
||||||
|
{
|
||||||
|
ticks = 0;
|
||||||
|
intr_set_handler(0x20, timer_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timer_get()
|
||||||
|
{
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_set(uint64_t time)
|
||||||
|
{
|
||||||
|
ticks = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sleep(uint64_t t)
|
||||||
|
{
|
||||||
|
uint64_t end = timer_get() + t;
|
||||||
|
while(timer_get() < end);
|
||||||
|
}
|
||||||
|
|
35
trainOS.pro
35
trainOS.pro
|
@ -12,23 +12,32 @@ SOURCES += \
|
||||||
src/stdlib.c \
|
src/stdlib.c \
|
||||||
src/vmm.c \
|
src/vmm.c \
|
||||||
trainscript/tsvm.cpp \
|
trainscript/tsvm.cpp \
|
||||||
trainscript/main.cpp
|
trainscript/main.cpp \
|
||||||
|
src/timer.c \
|
||||||
|
src/cplusplus.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/console.h \
|
include/console.h \
|
||||||
src/cpustate.h \
|
include/cpustate.h \
|
||||||
src/interrupts.h \
|
include/interrupts.h \
|
||||||
src/intr_stubs.h \
|
include/intr_stubs.h \
|
||||||
src/io.h \
|
include/io.h \
|
||||||
src/kernel.h \
|
include/kernel.h \
|
||||||
src/multiboot.h \
|
include/multiboot.h \
|
||||||
src/pmm.h \
|
include/pmm.h \
|
||||||
src/stdlib.h \
|
include/stdlib.h \
|
||||||
src/varargs.h \
|
include/varargs.h \
|
||||||
src/vmm.h \
|
include/vmm.h \
|
||||||
trainscript/common.h \
|
trainscript/common.h \
|
||||||
trainscript/tsvm.hpp \
|
trainscript/tsvm.hpp \
|
||||||
trainscript/typeid.hpp
|
trainscript/typeid.hpp \
|
||||||
|
include/timer.h \
|
||||||
|
include/ker/string.hpp \
|
||||||
|
include/ker/pair.hpp \
|
||||||
|
include/ker/vector.hpp \
|
||||||
|
include/ker/dictionary.hpp \
|
||||||
|
include/string.h \
|
||||||
|
include/ker/new.hpp
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
asm/intr_common_handler.S \
|
asm/intr_common_handler.S \
|
||||||
|
|
|
@ -15,10 +15,10 @@ main.o: main.cpp tsvm.hpp common.h
|
||||||
tsvm.o: tsvm.cpp tsvm.hpp common.h
|
tsvm.o: tsvm.cpp tsvm.hpp common.h
|
||||||
g++ $(CCFLAGS) -c tsvm.cpp -o tsvm.o
|
g++ $(CCFLAGS) -c tsvm.cpp -o tsvm.o
|
||||||
|
|
||||||
lex.yy.o: lex.yy.cpp tsvm.hpp common.h
|
lex.yy.o: lexyy.cpp tsvm.hpp common.h
|
||||||
g++ $(CCFLAGS) -c lex.yy.cpp -o lex.yy.o
|
g++ $(CCFLAGS) -c lex.yy.cpp -o lex.yy.o
|
||||||
|
|
||||||
trainscript.tab.o: lex.yy.cpp trainscript.tab.cpp tsvm.hpp common.h
|
trainscript.tab.o: lex.yy.cpp trainscript_tab.cpp tsvm.hpp common.h
|
||||||
g++ $(CCFLAGS) -c trainscript.tab.cpp -o trainscript.tab.o
|
g++ $(CCFLAGS) -c trainscript.tab.cpp -o trainscript.tab.o
|
||||||
|
|
||||||
lex.yy.cpp: trainscript.l
|
lex.yy.cpp: trainscript.l
|
||||||
|
|
|
@ -36,6 +36,7 @@ BEGIN
|
||||||
1 → iter;
|
1 → iter;
|
||||||
0 → r;
|
0 → r;
|
||||||
WHILE iter < max DO
|
WHILE iter < max DO
|
||||||
|
# FOR iter FROM 1 TO max DO
|
||||||
BEGIN
|
BEGIN
|
||||||
IF (iter % 5) = 0 THEN
|
IF (iter % 5) = 0 THEN
|
||||||
r + iter → r;
|
r + iter → r;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%{
|
%{
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "trainscript.tab.h"
|
#include "trainscript.tab.hpp"
|
||||||
|
|
||||||
%}
|
%}
|
||||||
%option noyywrap
|
%option noyywrap
|
||||||
|
|
128
trainscript/trainscript.tab.hpp
Normal file
128
trainscript/trainscript.tab.hpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/* A Bison parser, made by GNU Bison 3.0.4. */
|
||||||
|
|
||||||
|
/* Bison interface for Yacc-like parsers in C
|
||||||
|
|
||||||
|
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* As a special exception, you may create a larger work that contains
|
||||||
|
part or all of the Bison parser skeleton and distribute that work
|
||||||
|
under terms of your choice, so long as that work isn't itself a
|
||||||
|
parser generator using the skeleton or a modified version thereof
|
||||||
|
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||||
|
the parser skeleton itself, you may (at your option) remove this
|
||||||
|
special exception, which will cause the skeleton and the resulting
|
||||||
|
Bison output files to be licensed under the GNU General Public
|
||||||
|
License without this special exception.
|
||||||
|
|
||||||
|
This special exception was added by the Free Software Foundation in
|
||||||
|
version 2.2 of Bison. */
|
||||||
|
|
||||||
|
#ifndef YY_YY_TRAINSCRIPT_TRAINSCRIPT_TAB_HPP_INCLUDED
|
||||||
|
# define YY_YY_TRAINSCRIPT_TRAINSCRIPT_TAB_HPP_INCLUDED
|
||||||
|
/* Debug traces. */
|
||||||
|
#ifndef YYDEBUG
|
||||||
|
# define YYDEBUG 0
|
||||||
|
#endif
|
||||||
|
#if YYDEBUG
|
||||||
|
extern int yydebug;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Token type. */
|
||||||
|
#ifndef YYTOKENTYPE
|
||||||
|
# define YYTOKENTYPE
|
||||||
|
enum yytokentype
|
||||||
|
{
|
||||||
|
TAB = 258,
|
||||||
|
TYPENAME = 259,
|
||||||
|
SEMICOLON = 260,
|
||||||
|
COLON = 261,
|
||||||
|
COMMA = 262,
|
||||||
|
PIPE = 263,
|
||||||
|
PLUS = 264,
|
||||||
|
MINUS = 265,
|
||||||
|
MULTIPLY = 266,
|
||||||
|
DIVIDE = 267,
|
||||||
|
MODULO = 268,
|
||||||
|
LBRACKET = 269,
|
||||||
|
RBRACKET = 270,
|
||||||
|
RARROW = 271,
|
||||||
|
LARROW = 272,
|
||||||
|
OP_LT = 273,
|
||||||
|
OP_LE = 274,
|
||||||
|
OP_GT = 275,
|
||||||
|
OP_GE = 276,
|
||||||
|
OP_EQ = 277,
|
||||||
|
OP_NEQ = 278,
|
||||||
|
REAL = 279,
|
||||||
|
INT = 280,
|
||||||
|
IDENTIFIER = 281,
|
||||||
|
KW_PUB = 282,
|
||||||
|
KW_PRI = 283,
|
||||||
|
KW_VAR = 284,
|
||||||
|
KW_PTR = 285,
|
||||||
|
KW_VOID = 286,
|
||||||
|
KW_INT = 287,
|
||||||
|
KW_REAL = 288,
|
||||||
|
KW_TEXT = 289,
|
||||||
|
KW_BOOL = 290,
|
||||||
|
KW_BEGIN = 291,
|
||||||
|
KW_END = 292,
|
||||||
|
KW_IF = 293,
|
||||||
|
KW_THEN = 294,
|
||||||
|
KW_ELSE = 295,
|
||||||
|
KW_ELSEIF = 296,
|
||||||
|
KW_REPEAT = 297,
|
||||||
|
KW_FROM = 298,
|
||||||
|
KW_TO = 299,
|
||||||
|
KW_UNTIL = 300,
|
||||||
|
KW_WHILE = 301,
|
||||||
|
KW_DO = 302
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Value type. */
|
||||||
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||||
|
|
||||||
|
union YYSTYPE
|
||||||
|
{
|
||||||
|
#line 44 "trainscript/trainscript.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
|
float fval;
|
||||||
|
int ival;
|
||||||
|
char *text;
|
||||||
|
int indentation;
|
||||||
|
trainscript::Type type;
|
||||||
|
VariableDeclaration varDecl;
|
||||||
|
MethodDeclaration method;
|
||||||
|
MethodBody *body;
|
||||||
|
MethodHeader methodHeader;
|
||||||
|
trainscript::Instruction *instruction;
|
||||||
|
LocalVariable *local;
|
||||||
|
ExpressionList *expressions;
|
||||||
|
|
||||||
|
#line 117 "trainscript/trainscript.tab.hpp" /* yacc.c:1909 */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union YYSTYPE YYSTYPE;
|
||||||
|
# define YYSTYPE_IS_TRIVIAL 1
|
||||||
|
# define YYSTYPE_IS_DECLARED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int yyparse (ParserData * context);
|
||||||
|
|
||||||
|
#endif /* !YY_YY_TRAINSCRIPT_TRAINSCRIPT_TAB_HPP_INCLUDED */
|
|
@ -400,13 +400,13 @@ typeName:
|
||||||
|
|
||||||
void yyerror(void *scanner, const char *s) {
|
void yyerror(void *scanner, const char *s) {
|
||||||
if(scanner == nullptr) {
|
if(scanner == nullptr) {
|
||||||
printf("Error: %s\n", s);
|
kprintf("Error: %s\n", s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int line = 0; // yyget_lineno(scanner);
|
int line = 0; // yyget_lineno(scanner);
|
||||||
int col = 0; //yyget_column(scanner);
|
int col = 0; //yyget_column(scanner);
|
||||||
char *text = yyget_text(scanner);
|
char *text = yyget_text(scanner);
|
||||||
printf(
|
kprintf(
|
||||||
"[%d:%d] Error: %s at '%s'\n",
|
"[%d:%d] Error: %s at '%s'\n",
|
||||||
line, col,
|
line, col,
|
||||||
s,
|
s,
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
extern "C" {
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <console.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include "tsvm.hpp"
|
#include "tsvm.hpp"
|
||||||
|
|
||||||
#include "trainscript.tab.h"
|
#include "trainscript.tab.hpp"
|
||||||
#include "trainscript.l.h"
|
#include "trainscript.l.h"
|
||||||
|
|
||||||
namespace trainscript
|
namespace trainscript
|
||||||
|
@ -74,39 +76,29 @@ namespace trainscript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable Method::invoke(std::vector<Variable> arguments)
|
Variable Method::invoke(ker::Vector<Variable> arguments)
|
||||||
{
|
{
|
||||||
LocalContext context(this->module);
|
LocalContext context(this->module);
|
||||||
|
|
||||||
for(auto var : this->module->variables)
|
for(auto var : this->module->variables)
|
||||||
{
|
{
|
||||||
context.insert({ var.first, var.second });
|
context.add(var.first, var.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->returnValue.second.type.usable()) {
|
if(this->returnValue.second.type.usable()) {
|
||||||
context.insert({ this->returnValue.first, &this->returnValue.second });
|
context.add(this->returnValue.first, &this->returnValue.second);
|
||||||
}
|
}
|
||||||
if(arguments.size() != this->arguments.size()) {
|
if(arguments.length() != this->arguments.length()) {
|
||||||
printf("MECKER anzahl!\n");
|
return Variable::Invalid;
|
||||||
return Variable();
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < this->arguments.size(); i++) {
|
for(size_t i = 0; i < this->arguments.length(); i++) {
|
||||||
if(this->arguments[i].second.type != arguments[i].type) {
|
if(this->arguments[i].second.type != arguments[i].type) {
|
||||||
printf("MECKER argtyp!\n");
|
return Variable::Invalid;
|
||||||
return Variable();
|
|
||||||
}
|
}
|
||||||
context.insert({this->arguments[i].first, new Variable(arguments[i]) });
|
context.add(this->arguments[i].first, new Variable(arguments[i]));
|
||||||
}
|
}
|
||||||
for(auto local : this->locals) {
|
for(auto local : this->locals) {
|
||||||
context.insert({ local.first, new Variable(local.second) });
|
context.add(local.first, new Variable(local.second));
|
||||||
}
|
|
||||||
|
|
||||||
if(verbose) {
|
|
||||||
printf("executing with local context:\n");
|
|
||||||
for(auto &ref : context)
|
|
||||||
{
|
|
||||||
printf(" %s : %s\n", ref.first.c_str(), typeName(ref.second->type.id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->block->execute(context);
|
this->block->execute(context);
|
||||||
|
@ -123,7 +115,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: printf("addition not supported for %s.\n", typeName(lhs.type.id)); break;
|
default: kprintf("addition not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +124,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: printf("subtraction not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
default: kprintf("subtraction not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +133,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: printf("multiplication not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
default: kprintf("multiplication not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +142,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: printf("division not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
default: kprintf("division not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +151,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: printf("modulo not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
default: kprintf("modulo not supported for %s.\n", typeName(lhs.type.id)); return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +162,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:
|
||||||
printf("equals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("equals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +174,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:
|
||||||
printf("inequals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("inequals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +186,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:
|
||||||
printf("equals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("equals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +197,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:
|
||||||
printf("equals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("equals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +208,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:
|
||||||
printf("equals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("equals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +219,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:
|
||||||
printf("equals not supported for %s.\n", typeName(lhs.type.id));
|
kprintf("equals not supported for %s.\n", typeName(lhs.type.id));
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
extern "C" {
|
||||||
#include <string>
|
#include <stdlib.h>
|
||||||
#include <vector>
|
#include <console.h>
|
||||||
#include <string.h>
|
}
|
||||||
|
|
||||||
|
// #include <map>
|
||||||
|
|
||||||
|
#include <ker/string.hpp>
|
||||||
|
#include <ker/vector.hpp>
|
||||||
|
#include <ker/dictionary.hpp>
|
||||||
|
|
||||||
|
// #include <vector>
|
||||||
|
// #include <string.h>
|
||||||
|
|
||||||
#include "typeid.hpp"
|
#include "typeid.hpp"
|
||||||
|
|
||||||
|
@ -32,7 +41,6 @@ namespace trainscript
|
||||||
}
|
}
|
||||||
|
|
||||||
Type dereference() const {
|
Type dereference() const {
|
||||||
if(pointer == 0) throw std::exception();
|
|
||||||
return { id, pointer - 1 };
|
return { id, pointer - 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,10 +80,10 @@ namespace trainscript
|
||||||
void printval() const
|
void printval() const
|
||||||
{
|
{
|
||||||
switch(this->type.id) {
|
switch(this->type.id) {
|
||||||
case TypeID::Int: printf("%d", this->integer); break;
|
case TypeID::Int: kprintf("%d", this->integer); break;
|
||||||
case TypeID::Real: printf("%f", this->real); break;
|
case TypeID::Real: kprintf("%f", this->real); break;
|
||||||
case TypeID::Bool: printf("%s", this->boolean ? "TRUE" : "FALSE"); break;
|
case TypeID::Bool: kprintf("%s", this->boolean ? "TRUE" : "FALSE"); break;
|
||||||
default: printf("???"); break;
|
default: kprintf("???"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,33 +115,24 @@ namespace trainscript
|
||||||
|
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
class LocalContext :
|
class LocalContext :
|
||||||
public std::map<std::string, Variable*>
|
public ker::Dictionary<ker::String, Variable*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Module * const module = nullptr;
|
Module * const module = nullptr;
|
||||||
|
|
||||||
LocalContext(Module *mod) :
|
LocalContext(Module *mod) :
|
||||||
std::map<std::string, Variable*>(),
|
ker::Dictionary<ker::String, Variable*>(),
|
||||||
module(mod)
|
module(mod)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int depth;
|
Variable *get(const ker::String &name)
|
||||||
|
|
||||||
LocalContext() : depth(0) { }
|
|
||||||
|
|
||||||
void indent() {
|
|
||||||
for(int i = 0; i < depth; i++) printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable *get(const std::string &name)
|
|
||||||
{
|
{
|
||||||
if(this->count(name) > 0) {
|
if(this->contains(name)) {
|
||||||
return this->at(name);
|
return this->at(name);
|
||||||
} else {
|
} else {
|
||||||
printf("Variable %s not found!\n", name.c_str());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +150,7 @@ namespace trainscript
|
||||||
public Instruction
|
public Instruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<Instruction*> instructions;
|
ker::Vector<Instruction*> instructions;
|
||||||
|
|
||||||
~Block() {
|
~Block() {
|
||||||
for(auto *instr : instructions) delete instr;
|
for(auto *instr : instructions) delete instr;
|
||||||
|
@ -171,23 +170,23 @@ namespace trainscript
|
||||||
Module *module;
|
Module *module;
|
||||||
Instruction *block;
|
Instruction *block;
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
std::vector<std::pair<std::string, Variable>> arguments;
|
ker::Vector<ker::Pair<ker::String, Variable>> arguments;
|
||||||
std::map<std::string, Variable> locals;
|
ker::Dictionary<ker::String, Variable> locals;
|
||||||
std::pair<std::string, Variable> returnValue;
|
ker::Pair<ker::String, Variable> returnValue;
|
||||||
|
|
||||||
Method(Module *module, Instruction *block) : module(module), block(block)
|
Method(Module *module, Instruction *block) : module(module), block(block)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable invoke(std::vector<Variable> arguments);
|
Variable invoke(ker::Vector<Variable> arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Module
|
class Module
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::map<std::string, Variable*> variables;
|
ker::Dictionary<ker::String, Variable*> variables;
|
||||||
std::map<std::string, Method*> methods;
|
ker::Dictionary<ker::String, Method*> methods;
|
||||||
public:
|
public:
|
||||||
Module();
|
Module();
|
||||||
~Module();
|
~Module();
|
||||||
|
@ -225,12 +224,6 @@ namespace trainscript
|
||||||
ConstantExpression(Variable value) : value(value) { }
|
ConstantExpression(Variable value) : value(value) { }
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(verbose) {
|
|
||||||
context.indent();
|
|
||||||
printf("constant: ");
|
|
||||||
this->value.printval();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -239,15 +232,10 @@ namespace trainscript
|
||||||
public Instruction
|
public Instruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string variableName;
|
ker::String variableName;
|
||||||
VariableExpression(std::string variableName) : variableName(variableName) { }
|
VariableExpression(ker::String variableName) : variableName(variableName) { }
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(verbose) {
|
|
||||||
context.indent();
|
|
||||||
printf("variable: %s\n", this->variableName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *var = context.get(this->variableName);
|
auto *var = context.get(this->variableName);
|
||||||
if(var == nullptr) {
|
if(var == nullptr) {
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
|
@ -261,9 +249,9 @@ namespace trainscript
|
||||||
public Instruction
|
public Instruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string variableName;
|
ker::String variableName;
|
||||||
Instruction *expression;
|
Instruction *expression;
|
||||||
VariableAssignmentExpression(std::string variableName, Instruction *expression) :
|
VariableAssignmentExpression(ker::String variableName, Instruction *expression) :
|
||||||
variableName(variableName),
|
variableName(variableName),
|
||||||
expression(expression)
|
expression(expression)
|
||||||
{
|
{
|
||||||
|
@ -272,19 +260,9 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(this->expression == nullptr) {
|
if(this->expression == nullptr) {
|
||||||
if(verbose) printf("Invalid instruction in assignment.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
if(verbose) context.depth++;
|
|
||||||
Variable result = this->expression->execute(context);
|
Variable result = this->expression->execute(context);
|
||||||
if(verbose) context.depth--;
|
|
||||||
|
|
||||||
if(verbose) {
|
|
||||||
context.indent();
|
|
||||||
printf("assign ");
|
|
||||||
result.printval();
|
|
||||||
printf(" to %s\n", this->variableName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable *target = context.get(this->variableName);
|
Variable *target = context.get(this->variableName);
|
||||||
if(target == nullptr) {
|
if(target == nullptr) {
|
||||||
|
@ -292,10 +270,6 @@ namespace trainscript
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target->type != result.type) {
|
if(target->type != result.type) {
|
||||||
if(verbose) printf(
|
|
||||||
"Assignment does not match: %s → %s\n",
|
|
||||||
typeName(result.type.id),
|
|
||||||
this->variableName.c_str());
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +277,7 @@ namespace trainscript
|
||||||
case TypeID::Int: target->integer = result.integer; break;
|
case TypeID::Int: target->integer = result.integer; break;
|
||||||
case TypeID::Real: target->real = result.real; break;
|
case TypeID::Real: target->real = result.real; break;
|
||||||
case TypeID::Bool: target->boolean = result.boolean; break;
|
case TypeID::Bool: target->boolean = result.boolean; break;
|
||||||
default: if(verbose) printf("assignment not supported.\n"); break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -314,10 +288,10 @@ namespace trainscript
|
||||||
public Instruction
|
public Instruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string methodName;
|
ker::String methodName;
|
||||||
std::vector<Instruction*> parameters;
|
ker::Vector<Instruction*> parameters;
|
||||||
|
|
||||||
MethodInvokeExpression(std::string methodName) :
|
MethodInvokeExpression(ker::String methodName) :
|
||||||
methodName(methodName)
|
methodName(methodName)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -325,18 +299,16 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override
|
Variable execute(LocalContext &context) const override
|
||||||
{
|
{
|
||||||
Method *method = context.module->method(this->methodName.c_str());
|
Method *method = context.module->method(this->methodName.str());
|
||||||
if(method == nullptr) {
|
if(method == nullptr) {
|
||||||
if(verbose) printf("method %s not found!\n", this->methodName.c_str());
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose) context.depth++;
|
ker::Vector<Variable> vars(this->parameters.length());
|
||||||
std::vector<Variable> vars(this->parameters.size());
|
vars.resize(this->parameters.length());
|
||||||
for(int i = 0; i < vars.size(); i++) {
|
for(size_t i = 0; i < vars.length(); i++) {
|
||||||
vars[i] = this->parameters.at(i)->execute(context);
|
vars[i] = this->parameters.at(i)->execute(context);
|
||||||
}
|
}
|
||||||
if(verbose) context.depth--;
|
|
||||||
|
|
||||||
return method->invoke(vars);
|
return method->invoke(vars);
|
||||||
}
|
}
|
||||||
|
@ -347,7 +319,7 @@ namespace trainscript
|
||||||
public Instruction
|
public Instruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Instruction *rhs, *lhs;
|
Instruction *lhs, *rhs;
|
||||||
|
|
||||||
ArithmeticExpression(Instruction *lhs, Instruction *rhs) :
|
ArithmeticExpression(Instruction *lhs, Instruction *rhs) :
|
||||||
lhs(lhs),
|
lhs(lhs),
|
||||||
|
@ -358,36 +330,19 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(this->lhs == nullptr) {
|
if(this->lhs == nullptr) {
|
||||||
if(verbose) printf("lhs: Invalid instruction in addition.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
if(this->rhs == nullptr) {
|
if(this->rhs == nullptr) {
|
||||||
if(verbose) printf("rhs: Invalid instruction in addition.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose) context.depth++;
|
|
||||||
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(verbose) context.depth--;
|
|
||||||
|
|
||||||
if(left.type != right.type) {
|
if(left.type != right.type) {
|
||||||
if(verbose) printf(
|
|
||||||
"Arithmetic types do not match: %s != %s\n",
|
|
||||||
typeName(left.type.id),
|
|
||||||
typeName(right.type.id));
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose) {
|
|
||||||
context.indent();
|
|
||||||
printf("Arithmetic on ");
|
|
||||||
left.printval();
|
|
||||||
printf(" and ");
|
|
||||||
right.printval();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return OP(left, right);
|
return OP(left, right);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -410,13 +365,11 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(this->condition == nullptr) {
|
if(this->condition == nullptr) {
|
||||||
if(verbose) printf("IF: missing condition.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable result = this->condition->execute(context);
|
Variable result = this->condition->execute(context);
|
||||||
if(result.type != Type::Boolean) {
|
if(result.type != Type::Boolean) {
|
||||||
if(verbose) printf("IF: Invalid condition type.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
if((result.boolean == true) && (this->blockTrue != nullptr)) {
|
if((result.boolean == true) && (this->blockTrue != nullptr)) {
|
||||||
|
@ -443,7 +396,6 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(this->block == nullptr) {
|
if(this->block == nullptr) {
|
||||||
if(verbose) printf("REPEAT: missing block.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,23 +425,18 @@ namespace trainscript
|
||||||
|
|
||||||
Variable execute(LocalContext &context) const override {
|
Variable execute(LocalContext &context) const override {
|
||||||
if(this->condition == nullptr) {
|
if(this->condition == nullptr) {
|
||||||
if(verbose) printf("REPEAT: missing condition.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
if(this->block == nullptr) {
|
if(this->block == nullptr) {
|
||||||
if(verbose) printf("REPEAT: missing block.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
Variable cond = this->condition->execute(context);
|
Variable cond = this->condition->execute(context);
|
||||||
|
|
||||||
if(cond.type != Type::Boolean) {
|
if(cond.type != Type::Boolean) {
|
||||||
printf("REPEAT: Invalid expression type.\n");
|
|
||||||
return Variable::Invalid;
|
return Variable::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cond.boolean == false) {
|
if(cond.boolean == false) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue