Advertentie:

Auteur Topic: Interpreter datatype systeem  (gelezen 196 keer)

Offline ohlala

  • Groentje
  • *
  • Berichten: 4
Interpreter datatype systeem
« Gepost op: januari 19, 2012, 13:08:48 pm »
Hoi allemaal,

Ik ben nieuw hier en ik heb weinig ervaring met C++, het is niet mijn bedoeling om C++ te leren. Ik probeer een interpreter te maken omdat ik dat nodig heb voor een ander project in een andere taal.

Ik vroeg me af hoe ik dus het beste om kon gaan met verschillende datatypes. Ik wil namelijk een systeem maken waarmee variabelen gewijzigd kunnen worden met verschillende types. Ook wil ik het type id kunnen vragen.

Ik dacht er dus aan om een class de maken voor elk type dat de interpreter ondersteunt. Maar het probleem is dat ik dan geen idee heb hoe ik deze verschillende types in een stack/list/array te zetten.

Ik heb dus wat gezocht op internet.
Het union type was geen goede optie omdat dit te traag zou zijn.
Ik zoek een snelle manier om dit te bereiken. Dus kwam ik uit op boost.
Ik heb de classen any en varient van boost geprobeerd. Alleen ik krijg ze niet aan de praat op de manier hoe ik wil, bovendien crasht het nogal vaak zonder een foutmelding te geven dus dan weet ik niet wat ik fout doe.

Dit is de structuur van de functies die ik aan wil maken:
int id = var_create_string()
int id = var_create_double()
int id = var_create_list()
// of misschien beter:
int id = var_create(char type)
    char t_string = 1;
    char t_double = 2;
    char t_list = 3;
var_set(int id, std::string str)
var_set(int id, double num)
var_set(int id, ??)
std::string_str value = var_get(int id)
// En deze natuurlijk ook voor de andere datatypes.
char type = var_type(int id)
var_delete(int id)


Je snapt het idee. Het list type kan nog even overgeslagen worden want ik weet ook niet wat het handigst is voor het C++ type voor de list te gebruiken. In die list moeten dus ook weer var objecten kunnen worden geplaatst.

Ik vraag uiteraard niet voor voorgekauwde code, ik snap dat jullie dat niet willen doen.

Maar mijn vraag is hoe kan ik dit het beste aanpakken en hoe moet ik dat dan precies doen?

Nogmaals ik heb weinig ervaring met C++, ik heb dit nodig voor een ander project.

Ik hoop dat iemand mij hiermee kan helpen!

Alvast bedankt,

Ohlala
« Laatst bewerkt op: januari 19, 2012, 13:15:16 pm door ohlala »

Offline Divendo

  • Administrator
  • Zeer gerespecteerd lid
  • ********
  • Berichten: 2309
  • Voer in op google maps: 37.971458,23.726706
    • Divendo Webs
Re: Interpreter datatype systeem
« Reactie #1 Gepost op: januari 19, 2012, 14:42:03 pm »
Ik vraag me af waarom je dan opeens C++ nodig hebt voor dat project.
Kan dit niet in de taal die je dan al beheerst?

Om dit namelijk goed in elkaar te zetten is zeker wel kennis van C++ en ervaring met C++ vereist.
Dus zonder C++ te leren is dit eigenlijk onmogelijk.

Voordat we met oplossingen komen is het misschien handig te weten waarvoor dit nodig is.
De toepassing ervan beïnvloedt namelijk wat de beste methode is.
Admin - http://divendo-webs.com
[C++][PHP][JavaScript][HTML][XML][CSS][SQL][Bash][GML][Nederlands][Engels][Latijn]

"Leren is proberen."

Offline ohlala

  • Groentje
  • *
  • Berichten: 4
Re: Interpreter datatype systeem
« Reactie #2 Gepost op: januari 19, 2012, 20:56:49 pm »
Citaat
Ik vraag me af waarom je dan opeens C++ nodig hebt voor dat project.
Kan dit niet in de taal die je dan al beheerst?

Ik snap je verbazing, maar nee de talen die ik beheers zijn voornamelijk interpreter talen. Dus de snelheid ligt dan te laag. Ik heb gekozen voor c++ omdat dit een gecompileerde taal is, en dus voldoet aan de eisen.

Citaat
Om dit namelijk goed in elkaar te zetten is zeker wel kennis van C++ en ervaring met C++ vereist.
Dus zonder C++ te leren is dit eigenlijk onmogelijk.

Dat snap ik, ik heb wel kennis van andere talen. Ik ben van mening dat het dan toch een stuk makkelijker is om iets te creëren in c++. Ook heb ik wel enigzins ervaring met C++, maar ik loop nu op een obstakel waarbij ik niet weet hoe ik dit moet aanpakken.

Citaat
Voordat we met oplossingen komen is het misschien handig te weten waarvoor dit nodig is.
De toepassing ervan beïnvloedt namelijk wat de beste methode is.

Daarom heb ik de structuur van de functies gegeven waar ik naartoe wil werken. Ik heb de interpreter zelf al klaar, voornamelijk omdat ik dat afgeleid heb van Bison en CoCo. Ik snap verder wat ik heb geschreven, alleen wil ik er nog wat meer mogelijkheden in bouwen. Het enigste wat nog ontbreek is het gebruik van strings, aangezien nu alleen doubles verwerkt kunnen worden. Ook hoop ik nog meerdere datatypes in de bouwen daarom dus deze vraag. Anders had ik wel een omweg kunnen gebruiken.

Ik hoop dat iemand mij opweg kan helpen!

Offline TopTools

  • Nieuw lid
  • **
  • Berichten: 11
Re: Interpreter datatype systeem
« Reactie #3 Gepost op: januari 21, 2012, 20:45:54 pm »
Ik denk dat ik begrijp wat je wilt doen, in dat geval zou ik een class maken zoiets als:

class VarValue
{
  enum VarType { vtString, vtDouble, vtList };

  std::string stringVal;
  double doubleVal;
  std::list<VarValue> listVal;

  VarType varType;

public:

  SetValue(std::string stringVal)
  {
    this.stringVal = stringVal;
    this.varType = vtString;
  }

  SetValue(double doubleVal)
  {
    this.doubleVal = doubleVal;
    this.varType = vtDouble;
  }

  SetValue(std::list<VarValue> listVal)
  {
    this.listVal = listVal;
    this.varType = vtList;
  }

  std::string GetStringVal()
  {
    return this.stringVal;
  }

  double GetDoubleVal()
  {
    return this.doubleVal;
  }

  std::list<VarValue> GetListVal()
  {
    return this.listVal;
  }

};

Dit gaat niet zomaar werken omdat class VarValue nog aan een aantal extra voorwaarden moet voldoen (Hint: copy-constructor, operator=).

Offline Divendo

  • Administrator
  • Zeer gerespecteerd lid
  • ********
  • Berichten: 2309
  • Voer in op google maps: 37.971458,23.726706
    • Divendo Webs
Re: Interpreter datatype systeem
« Reactie #4 Gepost op: januari 22, 2012, 21:06:49 pm »
Daarbij is this een pointer en moet je dus een -> ipv een . schrijven ;)
Maar dat terzijde.

Je wilt dus eigenlijk een programmaatje dat code uitvoert maken.
In dat geval kun je misschien nog het makkelijkst een aantal lijsten maken met daarin de waarden per variabele naam.
Voorbeeld:
Code: C++
  1. // Mogelijke types
  2. enum Type
  3. {
  4.     typeInt,
  5.     typeDouble,
  6.     typeString
  7. };
  8.  
  9. // Bijhouden van welk type elke variabele is
  10. map<string, Type> allVars;
  11. map<string, int> intVars;
  12. map<string, double> doubleVars;
  13. map<string, string> stringVars;
  14.  
  15. // Variabele registreren:
  16. allVars["pi"] = typeDouble;
  17. doubleVars["pi"] = 3.14;
  18.  
  19. // Variabele opzoeken:
  20. switch(allVars["pi"])
  21. {
  22.     case typeInt:
  23.     return intVars["pi"];
  24.  
  25.     case typeDouble:
  26.     return doubleVars["pi"];
  27.  
  28.     case typeString:
  29.     return stringVars["pi"];
  30. }

Uiteraard is dit geen kopieer-plak code (mag wel, maar zou het niet aanraden) maar meer code om je een idee te geven van hoe je het kan aanpakken :)
Admin - http://divendo-webs.com
[C++][PHP][JavaScript][HTML][XML][CSS][SQL][Bash][GML][Nederlands][Engels][Latijn]

"Leren is proberen."

Offline TopTools

  • Nieuw lid
  • **
  • Berichten: 11
Re: Interpreter datatype systeem
« Reactie #5 Gepost op: januari 23, 2012, 00:08:29 am »
Citaat
Daarbij is this een pointer en moet je dus een -> ipv een . schrijven ;)

Oeps, je hebt gelijk, ik doe misschien teveel Python de laatste tijd..

Offline ohlala

  • Groentje
  • *
  • Berichten: 4
Re: Interpreter datatype systeem
« Reactie #6 Gepost op: januari 23, 2012, 14:43:12 pm »
Oke, ik had nog wat gezocht, en ik heb er voor besloten om het met arrays te doen:

Code: C++
  1. #if !defined(__MTYPE_H__)
  2. #define __MTYPE_H__
  3. #include <string>
  4. #include "flist.h"
  5.  
  6. struct var
  7. {
  8.     char type;
  9.     int id;  
  10. };
  11.  
  12. class cmem
  13. {
  14. public:
  15.     char t_str, t_int;
  16.     // Integer
  17.     int t_int_size;
  18.     int *t_int_mem;
  19.     int t_int_pos;
  20.     FList t_int_free;
  21.    
  22.     // String
  23.     int t_str_size;
  24.     std::string *t_str_mem;
  25.     int t_str_pos;
  26.     FList t_str_free;
  27.    
  28.     cmem()
  29.     {
  30.                 t_int = 0;
  31.                 t_str = 1;
  32.                
  33.                 t_int_size = 10;
  34.         t_int_mem = new int[t_int_size];
  35.         t_int_pos = 0;  
  36.        
  37.        
  38.         t_str_size = 100;
  39.         t_str_mem = new std::string[t_str_size];
  40.         t_str_pos = 0;  
  41.     }
  42.    
  43.     ~cmem()
  44.     {
  45.         delete [] t_int_mem;  
  46.     }
  47.    
  48.    
  49.     // Integer
  50.     var int_create(int v)
  51.     {
  52.         int p;
  53.         if (t_int_free.size()>0)
  54.         {
  55.             p = t_int_free.get(0);
  56.             t_int_free.del(0);  
  57.         }
  58.         else
  59.         {
  60.             p = t_int_pos++;
  61.         }
  62.        
  63.         t_int_mem[p] = v;
  64.         var i;
  65.         i.id = p;
  66.         i.type = t_int;  
  67.         return i;
  68.     }
  69.    
  70.     int int_get(var v)
  71.     {
  72.         return t_int_mem[v.id];
  73.     }
  74.    
  75.     int int_ptr(var v)
  76.     {
  77.         return v.id;
  78.     }  
  79.    
  80.     void int_set(var v, int i)
  81.     {
  82.         t_int_mem[v.id] = i;  
  83.     }
  84.    
  85.     void int_del(var v)
  86.     {
  87.         t_int_free.add(v.id);
  88.     }  
  89.    
  90.     // String
  91.     var str_create(std::string v)
  92.     {
  93.         int p;
  94.         if (t_str_free.size()>0)
  95.         {
  96.             p = t_str_free.get(0);
  97.             t_str_free.del(0);  
  98.         }
  99.         else
  100.         {
  101.             p = t_str_pos++;
  102.         }
  103.        
  104.         t_str_mem[p] = v;
  105.         var i;
  106.         i.id = p;
  107.         i.type = t_str;  
  108.         return i;
  109.     }
  110.    
  111.     std::string str_get(var v)
  112.     {
  113.         return t_str_mem[v.id];
  114.     }
  115.    
  116.     int str_ptr(var v)
  117.     {
  118.         return v.id;
  119.     }  
  120.    
  121.     void str_set(var v, std::string s)
  122.     {
  123.         t_str_mem[v.id] = s;  
  124.     }
  125.    
  126.     void str_del(var v)
  127.     {
  128.         t_str_free.add(v.id);
  129.     }  
  130. } m;
  131. #endif

En dit werkt, nu mijn vraag, is het mogelijk om de +, -, /, * en = operator in te bouwen in de struct var, of als ik daar een class van maak?
Op die manier is het wat overzichtelijker en misschien ook sneller.

Even een voorbeeldje bij mijn vraag:
Code: C++
  1. var a = int_create(32);
  2. var b = int_create(48);
  3.  
  4. var c = a + b;
  5.  

Ik hoop dat iemand mij hier op weg kan helpen.
Bedankt voor jullie reacties overigens!

Offline Divendo

  • Administrator
  • Zeer gerespecteerd lid
  • ********
  • Berichten: 2309
  • Voer in op google maps: 37.971458,23.726706
    • Divendo Webs
Re: Interpreter datatype systeem
« Reactie #7 Gepost op: januari 23, 2012, 16:12:40 pm »
Een struct en een class zijn exact hetzelfde, behalve dat bij een class alles by default private is en in een struct is het by default public.
Wat je dus gebruikt maakt niet uit.

Wat betreft je vraag over de operators, ja dat kan.
Ik heb je code niet doorgekeken, maar het volgende voorbeeld zal denk ik wel voor zich spreken.
Code: C++
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. // De class
  6. class var
  7. {
  8.     public:
  9.         // Hier gaan we de waarde in opslaan
  10.         int value;
  11.  
  12.         // Constructor
  13.         var(const int& value = 0)
  14.         : value(value) {}
  15.  
  16.         // Hier gaan we je operator implementeren
  17.         // Zoals je ziet is een zelf gemaakte operator in C++ dus niks meer dan een member functie met een vreemde naam
  18.         int operator+(const int& other)     // Een versie om gewone ints hierbij op te tellen
  19.         { return value + other; }
  20.         int operator+(const var& other)     // Een versie om andere instanties van deze class hierbij op te tellen
  21.         { return value + other.value; }
  22.  
  23.         // Misschien ook wel leuk om te weten, hiermee kan een impliciete conversie naar een int gedaan worden
  24.         // Dat betekent dus eigenlijk dat deze class hierdoor gewoon als int gebruikt kan worden
  25.         operator int&()
  26.         { return value; }
  27. };
  28.  
  29. // Class testen
  30. int main()
  31. {
  32.     // Twee instanties van je class maken
  33.     var a(11);
  34.     var b = a + 5;                          // Hier gebruiken we dus de + operator v/d class
  35.  
  36.     // Controleren of het werkt
  37.     cout<<"a = "<<a<<'\n';
  38.     cout<<"b = "<<b<<'\n';
  39.     cout<<'\n';
  40.     cout<<"a + b =\n";
  41.     cout<<a<<" + "<<b<<" = "<<(a+b);        // Weer de operator +
  42.  
  43.     // Voor Windows systemen: zodat de terminal niet direct afsluit
  44.     cin.get();
  45. }
  46.  
Admin - http://divendo-webs.com
[C++][PHP][JavaScript][HTML][XML][CSS][SQL][Bash][GML][Nederlands][Engels][Latijn]

"Leren is proberen."

Offline ohlala

  • Groentje
  • *
  • Berichten: 4
Re: Interpreter datatype systeem
« Reactie #8 Gepost op: januari 24, 2012, 18:29:23 pm »
Dit is precies wat ik nodig heb! Bedankt, hier heb ik echt wat aan.

Ik heb nog 3 vragen:

Aangezien het hier om variabelen gaat, is het dan onveilig om dit public te maken? Of is private misschien handiger?

Ik wil dit in combinatie doen met subclasses van var, waarbij de subclasses de verschillende datatypes zijn. Ik denk dat dit gaat lukken maar worden er dan telkens 2 instanties aangeroepen voor een variable? Maakt het dit niet langzamer?

En de laatste: Ik ben er nog niet uit, hoe ik de source code opsla. De interpreter is een LR(1) parser voor bytecode. Ik heb het nu dus in een char array staan. Wat natuurlijk niet de beste manier is om doubles/strings/lists in de casten en terug te halen. Nu doe ik dat met een union. Dit lijkt mij wat aan de langzame kant. Dus ik dacht, als ik eerst alle constanten eruit haal. deze in bijvoorbeeld een array per type zet / var classen van maak. En vervolgens de operators uit te voeren. Zou dit sneller zijn aangezien ik dan alleen maar meer classen aan maak? Zo niet, wat is dan de beste oplossing voor dit probleem?

Offline Divendo

  • Administrator
  • Zeer gerespecteerd lid
  • ********
  • Berichten: 2309
  • Voer in op google maps: 37.971458,23.726706
    • Divendo Webs
Re: Interpreter datatype systeem
« Reactie #9 Gepost op: januari 26, 2012, 12:52:15 pm »
Ik snap alleen je eerste vraag goed, daar kan ik dan ook voor je op antwoorden:
Het is uiteraard niet gevaarlijk een variabele public te maken, tenminste in dit geval niet.

Soms heb je variabelen waar je class bij vanuit moet kunnen gaan dat ze niet gewijzigd worden.
Bijvoorbeeld als jij een blok dynamisch geheugen van ints hebt aangevraagd, moet je weten hoeveel ints erin passen.
Dit sla je dan op in een variabele, die maak je uiteraard private (of protected) want daar moeten andere classes en functies niet aan zitten.
De pointer naar dat blok geheugen wil je ook niet public maken omdat dan opeens veranderd kan worden waar hij naar wijst zonder dat de class dat weet.

In dit geval maakt het de class niet uit wat de waarde van value is.
Dan is het alleen maar handiger en sneller als je die gewoon publiekelijk toegankelijk maakt ipv getters en setters te schrijven.
Admin - http://divendo-webs.com
[C++][PHP][JavaScript][HTML][XML][CSS][SQL][Bash][GML][Nederlands][Engels][Latijn]

"Leren is proberen."

Advertentie: