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)))
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LD = ld
|
||||
LEX=flex
|
||||
YACC=bison
|
||||
|
||||
# define nullptr, but not NULL.
|
||||
CFLAGS = -m32 -Dnullptr=0
|
||||
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
|
||||
|
||||
kernel: $(OBJS)
|
||||
kernel: $(OBJS) obj/tsvm.o obj/lex.yy.o obj/trainscript.tab.o
|
||||
$(LD) $(LDFLAGS) -o $@ $(addprefix obj/, $(notdir $^))
|
||||
|
||||
%.o: %.c
|
||||
|
@ -19,6 +23,24 @@ kernel: $(OBJS)
|
|||
%.o: %.S
|
||||
$(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:
|
||||
rm $(addprefix obj/, $(notdir $(OBJS)))
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CONSOLE_WIDTH 80
|
||||
#define CONSOLE_HEIGHT 25
|
||||
|
||||
|
@ -72,3 +76,7 @@ void kputs(const char *str);
|
|||
* @param ... The format parameters that will be used to print the string.
|
||||
*/
|
||||
void kprintf(const char *format, ...);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -1,6 +1,10 @@
|
|||
#pragma once
|
||||
#include "inttypes.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Saved by interrupt routine
|
||||
|
@ -22,3 +26,7 @@ typedef struct
|
|||
uint32_t esp;
|
||||
uint32_t ss;
|
||||
} CpuState;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -1,4 +1,9 @@
|
|||
#pragma once
|
||||
#include "cpustate.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GDTF_DATASEG 0x02
|
||||
#define GDTF_CODESEG 0x0a
|
||||
|
@ -16,11 +21,20 @@
|
|||
#define INTR_TRAP_GATE 7
|
||||
#define INTR_TASK_GATE 5
|
||||
|
||||
typedef void (*InterruptHandler)(CpuState *);
|
||||
|
||||
/**
|
||||
* Initializes interrupt handling and the global descriptor table.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -37,3 +51,6 @@ static inline void irq_disable(void)
|
|||
__asm__ volatile("cli");
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -1,6 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "inttypes.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @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));
|
||||
}
|
||||
|
||||
#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>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MB_MEMSIZE (1<<0)
|
||||
#define MB_BOOTDEVICE (1<<1)
|
||||
#define MB_COMMANDLINE (1<<2)
|
||||
|
@ -89,3 +93,7 @@ typedef struct {
|
|||
uint16_t vbeInterfaceOffset;
|
||||
uint16_t vbeInterfaceLength;
|
||||
} __attribute__((packed)) MultibootStructure;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include "multiboot.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initializes physical memory management.
|
||||
* @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.
|
||||
*/
|
||||
uint32_t pmm_calc_free(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -4,6 +4,10 @@
|
|||
#include <inttypes.h>
|
||||
#include "varargs.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *itoa(int value, char *str, int base);
|
||||
int atoi(const char *str);
|
||||
float atof(const char *str);
|
||||
|
@ -21,6 +25,10 @@ void *malloc(size_t size);
|
|||
*/
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
while(*source)
|
||||
|
@ -79,3 +101,15 @@ static inline void *calloc(size_t size)
|
|||
memset(mem, 0, size);
|
||||
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
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
#define va_start(ap, X) __builtin_va_start(ap, X)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VM_PRESENT 0x01
|
||||
#define VM_WRITABLE 0x02
|
||||
#define VM_USER 0x04
|
||||
|
@ -19,3 +23,7 @@ void vmm_init(void);
|
|||
* @remarks If flags is 0, the mapping will be undone.
|
||||
*/
|
||||
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 );
|
||||
}
|
66
src/init.c
66
src/init.c
|
@ -1,9 +1,11 @@
|
|||
#include "kernel.h"
|
||||
#include "stdlib.h"
|
||||
#include "console.h"
|
||||
#include "interrupts.h"
|
||||
#include "pmm.h"
|
||||
#include "vmm.h"
|
||||
#include <kernel.h>
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
#include <interrupts.h>
|
||||
#include <pmm.h>
|
||||
#include <vmm.h>
|
||||
|
||||
#include <timer.h>
|
||||
|
||||
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()
|
||||
{
|
||||
char buffer[64];
|
||||
|
@ -101,6 +94,18 @@ static void dumpMB(const MultibootStructure *mbHeader)
|
|||
// 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)debug_test;
|
||||
|
@ -114,36 +119,41 @@ void init(const MultibootStructure *mbHeader)
|
|||
|
||||
kputs("Initialize physical memory management: ");
|
||||
pmm_init(mbHeader);
|
||||
kputs("success.\n");
|
||||
putsuccess();
|
||||
|
||||
// uint32_t freeMem = pmm_calc_free();
|
||||
//kprintf("Free memory: %d B, %d kB, %d MB\n", freeMem, freeMem >> 10, freeMem >> 20);
|
||||
|
||||
ksleep(1);
|
||||
|
||||
kputs("Initialize virtual memory management: ");
|
||||
vmm_init();
|
||||
kputs("success.\n");
|
||||
putsuccess();
|
||||
|
||||
kputs("Initialize interrupts: ");
|
||||
kputs("Initialize interrupts:");
|
||||
intr_init();
|
||||
kputs("success.\n");
|
||||
putsuccess();
|
||||
|
||||
kputs("Enable hw interrupts: ");
|
||||
kputs("Enable hw interrupts:");
|
||||
irq_enable();
|
||||
kputs("success.\n");
|
||||
putsuccess();
|
||||
|
||||
//__asm__ volatile("sti");
|
||||
|
||||
kputs("Prepare heap memory: ");
|
||||
kputs("Prepare heap memory:");
|
||||
for(uintptr_t ptr = 0x400000; ptr < 0x800000; ptr += 4096)
|
||||
{
|
||||
vmm_map(ptr, (uintptr_t)pmm_alloc(), VM_PROGRAM);
|
||||
}
|
||||
kputs("success.\n");
|
||||
putsuccess();
|
||||
|
||||
kputs("Initialize timer:");
|
||||
timer_init();
|
||||
putsuccess();
|
||||
|
||||
kputs("Initialize C++ objects: ");
|
||||
cpp_init();
|
||||
putsuccess();
|
||||
|
||||
while(1)
|
||||
{
|
||||
kputs("x");
|
||||
ksleep(1);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
static uint64_t gdt[GDT_ENTRIES];
|
||||
static uint64_t idt[IDT_ENTRIES];
|
||||
|
||||
static InterruptHandler handlers[IDT_ENTRIES];
|
||||
|
||||
static const char *interruptNames[] = {
|
||||
"Divide-by-zero Error",// 0 (0x0) Fault #DE 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"
|
||||
|
||||
void intr_set_handler(uint32_t interrupt, InterruptHandler handler)
|
||||
{
|
||||
if(interrupt < IDT_ENTRIES) {
|
||||
handlers[interrupt] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void intr_routine(CpuState *state)
|
||||
{
|
||||
const char *name = "Unknown";
|
||||
if(state->intr < interruptNameCount)
|
||||
name = interruptNames[state->intr];
|
||||
InterruptHandler handler = handlers[state->intr];
|
||||
if(state->intr < 0x20)
|
||||
{
|
||||
if(handler != nullptr) {
|
||||
handler(state);
|
||||
} else {
|
||||
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(handler != nullptr) {
|
||||
handler(state);
|
||||
} else {
|
||||
kprintf("[Unhandled IRQ: %d]", state->intr);
|
||||
}
|
||||
|
||||
if (state->intr >= 0x28)
|
||||
{
|
||||
// EOI an Slave-PIC
|
||||
|
@ -90,6 +110,9 @@ void intr_routine(CpuState *state)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(handler != nullptr) {
|
||||
handler(state);
|
||||
} else {
|
||||
kprintf("\n\x12\x04Interrupt [%d] %s occurred!\x12\0x7\n", state->intr, name);
|
||||
while(1)
|
||||
{
|
||||
|
@ -97,6 +120,7 @@ void intr_routine(CpuState *state)
|
|||
__asm__ volatile("cli; hlt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gdt_entry(int i, uint32_t base, uint32_t limit, int flags)
|
||||
|
@ -240,8 +264,16 @@ static void init_idt(void)
|
|||
__asm__ volatile("lidt %0" : : "m" (idtp));
|
||||
}
|
||||
|
||||
void init_handlers(void)
|
||||
{
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
}
|
||||
|
||||
void intr_init(void)
|
||||
{
|
||||
// Initialize handler table
|
||||
init_handlers();
|
||||
|
||||
// Initialize global descriptor table
|
||||
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)
|
||||
{
|
||||
|
|
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/vmm.c \
|
||||
trainscript/tsvm.cpp \
|
||||
trainscript/main.cpp
|
||||
trainscript/main.cpp \
|
||||
src/timer.c \
|
||||
src/cplusplus.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/console.h \
|
||||
src/cpustate.h \
|
||||
src/interrupts.h \
|
||||
src/intr_stubs.h \
|
||||
src/io.h \
|
||||
src/kernel.h \
|
||||
src/multiboot.h \
|
||||
src/pmm.h \
|
||||
src/stdlib.h \
|
||||
src/varargs.h \
|
||||
src/vmm.h \
|
||||
include/console.h \
|
||||
include/cpustate.h \
|
||||
include/interrupts.h \
|
||||
include/intr_stubs.h \
|
||||
include/io.h \
|
||||
include/kernel.h \
|
||||
include/multiboot.h \
|
||||
include/pmm.h \
|
||||
include/stdlib.h \
|
||||
include/varargs.h \
|
||||
include/vmm.h \
|
||||
trainscript/common.h \
|
||||
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 += \
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
lex.yy.cpp: trainscript.l
|
||||
|
|
|
@ -36,6 +36,7 @@ BEGIN
|
|||
1 → iter;
|
||||
0 → r;
|
||||
WHILE iter < max DO
|
||||
# FOR iter FROM 1 TO max DO
|
||||
BEGIN
|
||||
IF (iter % 5) = 0 THEN
|
||||
r + iter → r;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%{
|
||||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
#include "trainscript.tab.h"
|
||||
#include "trainscript.tab.hpp"
|
||||
|
||||
%}
|
||||
%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) {
|
||||
if(scanner == nullptr) {
|
||||
printf("Error: %s\n", s);
|
||||
kprintf("Error: %s\n", s);
|
||||
return;
|
||||
}
|
||||
int line = 0; // yyget_lineno(scanner);
|
||||
int col = 0; //yyget_column(scanner);
|
||||
char *text = yyget_text(scanner);
|
||||
printf(
|
||||
kprintf(
|
||||
"[%d:%d] Error: %s at '%s'\n",
|
||||
line, col,
|
||||
s,
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <console.h>
|
||||
}
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "tsvm.hpp"
|
||||
|
||||
#include "trainscript.tab.h"
|
||||
#include "trainscript.tab.hpp"
|
||||
#include "trainscript.l.h"
|
||||
|
||||
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);
|
||||
|
||||
for(auto var : this->module->variables)
|
||||
{
|
||||
context.insert({ var.first, var.second });
|
||||
context.add(var.first, var.second);
|
||||
}
|
||||
|
||||
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()) {
|
||||
printf("MECKER anzahl!\n");
|
||||
return Variable();
|
||||
if(arguments.length() != this->arguments.length()) {
|
||||
return Variable::Invalid;
|
||||
}
|
||||
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) {
|
||||
printf("MECKER argtyp!\n");
|
||||
return Variable();
|
||||
return Variable::Invalid;
|
||||
}
|
||||
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) {
|
||||
context.insert({ 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));
|
||||
}
|
||||
context.add(local.first, new Variable(local.second));
|
||||
}
|
||||
|
||||
this->block->execute(context);
|
||||
|
@ -123,7 +115,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: 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) {
|
||||
case TypeID::Int: return mkvar(lhs.integer - rhs.integer);
|
||||
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) {
|
||||
case TypeID::Int: return mkvar(lhs.integer * rhs.integer);
|
||||
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) {
|
||||
case TypeID::Int: return mkvar(lhs.integer / rhs.integer);
|
||||
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) {
|
||||
case TypeID::Int: return mkvar(lhs.integer % rhs.integer);
|
||||
// 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::Bool: return mkbool(lhs.boolean == rhs.boolean);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +174,7 @@ namespace trainscript
|
|||
case TypeID::Real: return mkbool(lhs.real != rhs.real);
|
||||
case TypeID::Bool: return mkbool(lhs.boolean != rhs.boolean);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +186,7 @@ namespace trainscript
|
|||
case TypeID::Int: return mkbool(lhs.integer < rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real < rhs.real);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +197,7 @@ namespace trainscript
|
|||
case TypeID::Int: return mkbool(lhs.integer <= rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real <= rhs.real);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +208,7 @@ namespace trainscript
|
|||
case TypeID::Int: return mkbool(lhs.integer > rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real > rhs.real);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +219,7 @@ namespace trainscript
|
|||
case TypeID::Int: return mkbool(lhs.integer >= rhs.integer);
|
||||
case TypeID::Real: return mkbool(lhs.real >= rhs.real);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
}
|
||||
|
||||
// #include <map>
|
||||
|
||||
#include <ker/string.hpp>
|
||||
#include <ker/vector.hpp>
|
||||
#include <ker/dictionary.hpp>
|
||||
|
||||
// #include <vector>
|
||||
// #include <string.h>
|
||||
|
||||
#include "typeid.hpp"
|
||||
|
||||
|
@ -32,7 +41,6 @@ namespace trainscript
|
|||
}
|
||||
|
||||
Type dereference() const {
|
||||
if(pointer == 0) throw std::exception();
|
||||
return { id, pointer - 1 };
|
||||
}
|
||||
|
||||
|
@ -72,10 +80,10 @@ namespace trainscript
|
|||
void printval() const
|
||||
{
|
||||
switch(this->type.id) {
|
||||
case TypeID::Int: printf("%d", this->integer); break;
|
||||
case TypeID::Real: printf("%f", this->real); break;
|
||||
case TypeID::Bool: printf("%s", this->boolean ? "TRUE" : "FALSE"); break;
|
||||
default: printf("???"); break;
|
||||
case TypeID::Int: kprintf("%d", this->integer); break;
|
||||
case TypeID::Real: kprintf("%f", this->real); break;
|
||||
case TypeID::Bool: kprintf("%s", this->boolean ? "TRUE" : "FALSE"); break;
|
||||
default: kprintf("???"); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,32 +116,23 @@ namespace trainscript
|
|||
class Module;
|
||||
|
||||
class LocalContext :
|
||||
public std::map<std::string, Variable*>
|
||||
public ker::Dictionary<ker::String, Variable*>
|
||||
{
|
||||
public:
|
||||
Module * const module = nullptr;
|
||||
|
||||
LocalContext(Module *mod) :
|
||||
std::map<std::string, Variable*>(),
|
||||
ker::Dictionary<ker::String, Variable*>(),
|
||||
module(mod)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int depth;
|
||||
|
||||
LocalContext() : depth(0) { }
|
||||
|
||||
void indent() {
|
||||
for(int i = 0; i < depth; i++) printf(" ");
|
||||
}
|
||||
|
||||
Variable *get(const std::string &name)
|
||||
Variable *get(const ker::String &name)
|
||||
{
|
||||
if(this->count(name) > 0) {
|
||||
if(this->contains(name)) {
|
||||
return this->at(name);
|
||||
} else {
|
||||
printf("Variable %s not found!\n", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +150,7 @@ namespace trainscript
|
|||
public Instruction
|
||||
{
|
||||
public:
|
||||
std::vector<Instruction*> instructions;
|
||||
ker::Vector<Instruction*> instructions;
|
||||
|
||||
~Block() {
|
||||
for(auto *instr : instructions) delete instr;
|
||||
|
@ -171,23 +170,23 @@ namespace trainscript
|
|||
Module *module;
|
||||
Instruction *block;
|
||||
bool isPublic;
|
||||
std::vector<std::pair<std::string, Variable>> arguments;
|
||||
std::map<std::string, Variable> locals;
|
||||
std::pair<std::string, Variable> returnValue;
|
||||
ker::Vector<ker::Pair<ker::String, Variable>> arguments;
|
||||
ker::Dictionary<ker::String, Variable> locals;
|
||||
ker::Pair<ker::String, Variable> returnValue;
|
||||
|
||||
Method(Module *module, Instruction *block) : module(module), block(block)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable invoke(std::vector<Variable> arguments);
|
||||
Variable invoke(ker::Vector<Variable> arguments);
|
||||
};
|
||||
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
std::map<std::string, Variable*> variables;
|
||||
std::map<std::string, Method*> methods;
|
||||
ker::Dictionary<ker::String, Variable*> variables;
|
||||
ker::Dictionary<ker::String, Method*> methods;
|
||||
public:
|
||||
Module();
|
||||
~Module();
|
||||
|
@ -225,12 +224,6 @@ namespace trainscript
|
|||
ConstantExpression(Variable value) : value(value) { }
|
||||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(verbose) {
|
||||
context.indent();
|
||||
printf("constant: ");
|
||||
this->value.printval();
|
||||
printf("\n");
|
||||
}
|
||||
return this->value;
|
||||
}
|
||||
};
|
||||
|
@ -239,15 +232,10 @@ namespace trainscript
|
|||
public Instruction
|
||||
{
|
||||
public:
|
||||
std::string variableName;
|
||||
VariableExpression(std::string variableName) : variableName(variableName) { }
|
||||
ker::String variableName;
|
||||
VariableExpression(ker::String variableName) : variableName(variableName) { }
|
||||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(verbose) {
|
||||
context.indent();
|
||||
printf("variable: %s\n", this->variableName.c_str());
|
||||
}
|
||||
|
||||
auto *var = context.get(this->variableName);
|
||||
if(var == nullptr) {
|
||||
return Variable::Invalid;
|
||||
|
@ -261,9 +249,9 @@ namespace trainscript
|
|||
public Instruction
|
||||
{
|
||||
public:
|
||||
std::string variableName;
|
||||
ker::String variableName;
|
||||
Instruction *expression;
|
||||
VariableAssignmentExpression(std::string variableName, Instruction *expression) :
|
||||
VariableAssignmentExpression(ker::String variableName, Instruction *expression) :
|
||||
variableName(variableName),
|
||||
expression(expression)
|
||||
{
|
||||
|
@ -272,19 +260,9 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->expression == nullptr) {
|
||||
if(verbose) printf("Invalid instruction in assignment.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if(verbose) context.depth++;
|
||||
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);
|
||||
if(target == nullptr) {
|
||||
|
@ -292,10 +270,6 @@ namespace trainscript
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -303,7 +277,7 @@ namespace trainscript
|
|||
case TypeID::Int: target->integer = result.integer; break;
|
||||
case TypeID::Real: target->real = result.real; break;
|
||||
case TypeID::Bool: target->boolean = result.boolean; break;
|
||||
default: if(verbose) printf("assignment not supported.\n"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -314,10 +288,10 @@ namespace trainscript
|
|||
public Instruction
|
||||
{
|
||||
public:
|
||||
std::string methodName;
|
||||
std::vector<Instruction*> parameters;
|
||||
ker::String methodName;
|
||||
ker::Vector<Instruction*> parameters;
|
||||
|
||||
MethodInvokeExpression(std::string methodName) :
|
||||
MethodInvokeExpression(ker::String methodName) :
|
||||
methodName(methodName)
|
||||
{
|
||||
|
||||
|
@ -325,18 +299,16 @@ namespace trainscript
|
|||
|
||||
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(verbose) printf("method %s not found!\n", this->methodName.c_str());
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
if(verbose) context.depth++;
|
||||
std::vector<Variable> vars(this->parameters.size());
|
||||
for(int i = 0; i < vars.size(); i++) {
|
||||
ker::Vector<Variable> vars(this->parameters.length());
|
||||
vars.resize(this->parameters.length());
|
||||
for(size_t i = 0; i < vars.length(); i++) {
|
||||
vars[i] = this->parameters.at(i)->execute(context);
|
||||
}
|
||||
if(verbose) context.depth--;
|
||||
|
||||
return method->invoke(vars);
|
||||
}
|
||||
|
@ -347,7 +319,7 @@ namespace trainscript
|
|||
public Instruction
|
||||
{
|
||||
public:
|
||||
Instruction *rhs, *lhs;
|
||||
Instruction *lhs, *rhs;
|
||||
|
||||
ArithmeticExpression(Instruction *lhs, Instruction *rhs) :
|
||||
lhs(lhs),
|
||||
|
@ -358,36 +330,19 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->lhs == nullptr) {
|
||||
if(verbose) printf("lhs: Invalid instruction in addition.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if(this->rhs == nullptr) {
|
||||
if(verbose) printf("rhs: Invalid instruction in addition.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
if(verbose) context.depth++;
|
||||
Variable left = this->lhs->execute(context);
|
||||
Variable right = this->rhs->execute(context);
|
||||
if(verbose) context.depth--;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(verbose) {
|
||||
context.indent();
|
||||
printf("Arithmetic on ");
|
||||
left.printval();
|
||||
printf(" and ");
|
||||
right.printval();
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return OP(left, right);
|
||||
}
|
||||
};
|
||||
|
@ -410,13 +365,11 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->condition == nullptr) {
|
||||
if(verbose) printf("IF: missing condition.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
Variable result = this->condition->execute(context);
|
||||
if(result.type != Type::Boolean) {
|
||||
if(verbose) printf("IF: Invalid condition type.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if((result.boolean == true) && (this->blockTrue != nullptr)) {
|
||||
|
@ -443,7 +396,6 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->block == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing block.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
|
@ -473,23 +425,18 @@ namespace trainscript
|
|||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->condition == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing condition.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if(this->block == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing block.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
Variable cond = this->condition->execute(context);
|
||||
|
||||
if(cond.type != Type::Boolean) {
|
||||
printf("REPEAT: Invalid expression type.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
if(cond.boolean == false) {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue