Project GBX
Posted: Mon May 27, 2019 8:29 am
Hei vaan kaikille pitkästä aikaa! En tiedä lukeeko kukaan täällä enää mitään postauksia, mutta päätin nyt kuitenkin kirjoittaa.
Olen tässä CoolBasicistä insipoituneena kehitellyt vapaa-ajallani omaa virtuaalikonetta, joka nyt pääpiirteittäin toimii. Ideana olisi kasata sen päälle jokin CoolBasic:iä muistuttava Basic syntaksilla toimiva koodikieli ja siihen C++:lla taustalla toimiva pelimoottori.
Virtuaalikone on toteutettu C++:lla ja toimii tulkkiperiaatteella (compiler tekee keksimästäni "assemblystä" tavukoodia, jota virtuaalikone osaa suorittaa). Olen myös toteuttanut oman työkalun, joka osaa reflektoida natiiviluokat virtuaalikoneen käyttöön. Työkalun (build tool) avulla voin nopeasti lisätä uuden C++-funktion/luokan, joka tulee automaattisesti virtuaalikoneen käytettäväksi. Pääideanani oli saada tavukoodi toimimaan saumattomasti natiivikoodin kanssa, jolloin funktioita voidaan kutsua aina mistä vaan olkoon se sitten C++-funktio tai tavukoodissa toteutettu funktio.
Tällä hetkellä toimii funktiot (mukana myös virtual-funktiot), luokat (myös periytyminen), muuttujat, uusien objektien alustus luokasta, objektien propertyjen lukeminen ja kirjoittaminen, dynaaminen taulukko (myös objektitaulukot), dynaaminen map (key value pari), natiivi funktioiden kutsuminen sekä tavukoodiin luodun "event-funktion" kutsuminen C++-koodista.
Esimerkiksi Console-luokassa olen määritellyt "Print"-funktion, joka tulostaa tekstin konsoliin. GBX_FUNCTION()-macro kertoo build toolille, että funktio kuuluu reflektoida, jonka jälkeen työkalu generoi tarvittavat asiat funktion näkymiselle ja käyttämiselle virtuaalikoneessa.
Reflektointi makroille voidaan myös antaa parametreja, jotka muokkaavat generointia. Esim. GBX_CLASS(Static) tekee luokasta staattisen, jolloin kyseisestä luokasta ei voida alustaa objekteja. GBX_FUNCTION(ImplementableEvent)-parametrilla reflektoitu funktio generoi uuden C++-funktion, jota kutsumalla virtuaalikone suorittaa tavukoodiin määrietllyn toteutuksen kyseiselle funktiolle.
Esimerkki eventeistä:
Kutsumalla OnUpdate-funktiota C++-koodissa ajaa funktion toteutuksen tavukoodissa.
Oma "assembly"-koodini toimii välikielenä, jota olisi tarkoitus muodostaa Basic-syntaksi tyylisestä kielestä. Tällä hetkellä kieli näyttää kutakuinkin tältä:
Koodissa on kaksi luokkaa (NameClass ja NameClassDerived), joista NameClassDerived peritään NameClass:stä. NameClass sisältää yhden string-tyyppisen propertyn, joka voidaan asettaa SetName-funktiolla. GetName-funktio on määritelty virtuaaliseksi ja on ylikirjoitettu NameClassDerived-luokassa. Main-funktiossa luodaan uusi NameClassDerived-tyyppinen objekti, jolle kutsutaan GetName-funktiota (NameClass-versiota), jolloin virtuaali funktion takia kutsutaakin oikeasti NameClassDerived-luokassa määriteltyä funktiota. $EXEC name << Console:Print ()- rivi tulostaa name-nimisen muutujan konsoliin käyttäen ylempänä olevaa C++-luokan Print funktiota.
Seuraavan olisi tarkoitus lähteä miettimään, basic-syntaksia ja kääntäjää sille, joka tuottaa ylläolevaa koodia.
Olen tässä CoolBasicistä insipoituneena kehitellyt vapaa-ajallani omaa virtuaalikonetta, joka nyt pääpiirteittäin toimii. Ideana olisi kasata sen päälle jokin CoolBasic:iä muistuttava Basic syntaksilla toimiva koodikieli ja siihen C++:lla taustalla toimiva pelimoottori.
Virtuaalikone on toteutettu C++:lla ja toimii tulkkiperiaatteella (compiler tekee keksimästäni "assemblystä" tavukoodia, jota virtuaalikone osaa suorittaa). Olen myös toteuttanut oman työkalun, joka osaa reflektoida natiiviluokat virtuaalikoneen käyttöön. Työkalun (build tool) avulla voin nopeasti lisätä uuden C++-funktion/luokan, joka tulee automaattisesti virtuaalikoneen käytettäväksi. Pääideanani oli saada tavukoodi toimimaan saumattomasti natiivikoodin kanssa, jolloin funktioita voidaan kutsua aina mistä vaan olkoon se sitten C++-funktio tai tavukoodissa toteutettu funktio.
Tällä hetkellä toimii funktiot (mukana myös virtual-funktiot), luokat (myös periytyminen), muuttujat, uusien objektien alustus luokasta, objektien propertyjen lukeminen ja kirjoittaminen, dynaaminen taulukko (myös objektitaulukot), dynaaminen map (key value pari), natiivi funktioiden kutsuminen sekä tavukoodiin luodun "event-funktion" kutsuminen C++-koodista.
Code: Select all
#pragma once
#include "GBXCoreLib.h"
#include "GBXPlatform.h"
#if GBX_PLATFORM == GBX_PLATFORM_WINDOWS
#include <Windows.h>
#endif
#include "GBXConsole.gen.h"
GBX_GENERATE_FILE()
namespace GBX
{
GBX_CLASS(Static)
class Console
{
public:
GBX_GENERATED_BODY_Console()
public:
Console();
~Console();
// Prints line of text to the console
GBX_FUNCTION()
static void Print(gbx::string Text);
private:
};
GBX_END_CLASS()
}
Reflektointi makroille voidaan myös antaa parametreja, jotka muokkaavat generointia. Esim. GBX_CLASS(Static) tekee luokasta staattisen, jolloin kyseisestä luokasta ei voida alustaa objekteja. GBX_FUNCTION(ImplementableEvent)-parametrilla reflektoitu funktio generoi uuden C++-funktion, jota kutsumalla virtuaalikone suorittaa tavukoodiin määrietllyn toteutuksen kyseiselle funktiolle.
Esimerkki eventeistä:
Code: Select all
// Header
GBX_FUNCTION(ImplementableEvent)
void OnUpdate(gbx::float32 DeltaTime, gbx::int32 FrameCount, gbx::boolean SkipFrame);
//Cpp
void TestObjectClass::OnUpdate(gbx::float32 DeltaTime, gbx::int32 FrameCount, gbx::boolean SkipFrame)
{
ExecuteEventImplementation_OnUpdate(this, DeltaTime, FrameCount, SkipFrame);
}
Oma "assembly"-koodini toimii välikielenä, jota olisi tarkoitus muodostaa Basic-syntaksi tyylisestä kielestä. Tällä hetkellä kieli näyttää kutakuinkin tältä:
Code: Select all
$decl_class 1 NameClass ObjectBase
$property string Name
$decl_class 1 NameClassDerived ObjectBase
$parent NameClass
$decl_func 1 string GetName NameClass 1 0 0 0
$RET this NameClass:Name <<p
$decl_func 2 void SetName NameClass 0 0 0 1 name string
$EXEC name << this NameClass:Name =p
$RET
$decl_func 1 string GetName NameClassDerived 1 0 0 0
$RET this NameClass:Name <<p " added string .+.
$decl_func 9 int32 Main global 0 0 0 0
$BS
$REG ref obj
$EXEC NameClassDerived new obj =
$EXEC obj << . "Nimi NameClass:SetName (m)
$REG string name
$EXEC obj << . NameClass:GetName (v) name =
$EXEC name << Console:Print ()
$ES
$RET 0
Seuraavan olisi tarkoitus lähteä miettimään, basic-syntaksia ja kääntäjää sille, joka tuottaa ylläolevaa koodia.