It is currently Fri May 24, 2013 7:40 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: "variable" compiler constant?
PostPosted: Sat May 12, 2012 10:32 pm 
Offline
Enthusiast
Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
Demivec wrote:
Here's my shot:


Demivic,
Thanks for the suggestion. I think I will most likely end up with a combination of yours and boskers solution. Originally it was due to his issues with struct array sizes (now fixed), but the other disadvantage is that it and relies on assumptions made about the compiler. It is also a bigger solution, pb codewise, with all of the setup required. However, it is most likely the most compact exe code.

Although this final one not ideal since it uses that dreaded ReDim, it does work well, and will only be called once during startup. Perhaps not as ideal with numerous values, but for small lists, using the ReDim is more compact and easier to read--only one Macro, one Struct, and a single Dim before using it.

In the end, I think this will make its way into my code. Thanks again for all of the suggestions.

Code:
Macro Enum(colour, desc, value)
   ReDim color(#PB_Compiler_EnumerationValue)
   Enumeration #PB_Compiler_EnumerationValue
      #color#colour
   EndEnumeration
   color(#color#colour)\name = desc
   color(#color#colour)\RGB  = value
EndMacro
   
Structure colorName
   name.s
   RGB.i
EndStructure

Dim color.colorName(0)   ;#maxColor)

Enum(white, "White", $ffffff)
Enum(black, "Black", #Black)
Enum(red,   "Red", #Red)
Enum(last,   "ColorLast", 0)      ;   for use with continuing gadget Enum names.




Debug "white = " + Str(#colorwhite) + ", Name= " + color(#colorwhite)\name + ", Value: $" + Hex(color(#colorwhite)\RGB)
Debug "red = " + Str(#colorred) + ", Name= " + color(#colorred)\name + ", Value: $" + Hex(color(#colorred)\RGB)
Debug "black = " + Str(#colorblack) + ", Name= " + color(#colorblack)\name + ", Value: $" + Hex(color(#colorblack)\RGB)
Debug ""
Debug "ColorLast = " + Str(#ColorLast)

End


; Output results:

; white = 0, Name= White, Value: $FFFFFF
; red = 1, Name= Red, Value: $FF
; black = 2, Name= Black, Value: $0
;
; ColorLast = 3


; test reordering the Enum calls:
; white = 0, Name= White, Value: $FFFFFF
; red = 2, Name= Red, Value: $FF
; black = 1, Name= Black, Value: $0
;
; ColorLast = 3


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Thu May 17, 2012 10:44 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Aug 27, 2011 9:50 pm
Posts: 107
Location: Washington, USA
This looks like it might be loosely related to one of the tools I use in my compiler project. In case it's of any use, here it is.

Code:
; atoms.pb   --  Provides a mechanism for registering atoms and converting atoms back to text.
;       void (Amy Lear), 2012
;
;       Purpose: Allows a unified means of working with named values without constantly passing around strings.
;       With this system you can use atoms in both code and in data files, without worrying about pre-defined enumerations.
;
;       Inspired by erlang atoms, but obviously significantly less awesome without compiler support (which is in progress).



; AtomMax starts at 4K. Each time it hits this limit it re-sizes the table (doubling each time).
; If we excessively exceed this count string to atom lookups could eventually slow significantly.
; This bears examining.
Global AtomMax.i = 4096
Global NewMap AtomTable.i(AtomMax * 4)    ; 16k entries, just in case.
Global Dim AtomStrings.s(AtomMax)
Global AtomCount.i = 0


; null string is always the 0th atom and doesn't count against the total # of atoms in use.
AtomStrings(0) = ""
AtomTable("") = 0


; Ensures valid string input only.
; TODO: Possibly this should error out on invalid input?
; Currently skipping a lot of sanitization because the VM asks weird things.
Procedure.s SanitizeAtomString(InputString.s)
  Define OutputString.s, ThisChar.i
  InputString = LCase(Trim(InputString))
;  For i = 1 To Len(InputString)
;    ThisChar = Asc(Mid(InputString,i,1))
;    Select ThisChar
;      Case 46, 47, 48 To 57, 95, 141 To 172 ; Allowed characters: period, slash, numbers, underscore, lowercase letters
;        OutputString = OutputString + Chr(ThisChar)
;    EndSelect
;  Next i
  ProcedureReturn InputString
EndProcedure

; For when you simply need to know what atom a string matches to ONLY if it already exists as an atom.
; Remember to convert to lowercase if you're dealing with case insensitive strings.
Procedure.i VerifyAtom(InputString.s)
  Define *Atomptr, AtomNum
  If InputString = ""
    ProcedureReturn 0
  EndIf
 
  *Atomptr = FindMapElement(AtomTable(), InputString)
  If *Atomptr
    AtomNum = PeekI(*Atomptr)
  EndIf
  ProcedureReturn AtomNum
EndProcedure

; For if you absolutely must have an atom result from your exact string. Use with care.
; Strings for case insensitive contexts need to be converted to lowercase first. newatom() below will do this.
Procedure.i StringtoAtom(InputString.s)
  Define AtomNum.i
  If InputString = ""
    ProcedureReturn 0
  EndIf
  AtomNum.i = VerifyAtom(InputString)
  If Not AtomNum
    If AtomCount = AtomMax
      AtomMax * 2
      ReDim AtomStrings.s(AtomMax)
    EndIf
    AtomCount + 1
    AtomNum = AtomCount
    AtomTable(InputString) = AtomNum
    AtomStrings(AtomNum) = InputString
  EndIf
  ProcedureReturn AtomNum
EndProcedure

Procedure.i newatom(InputString.s)
  ProcedureReturn StringtoAtom(SanitizeAtomString(InputString))
EndProcedure


Procedure.s AtomToString(InputAtom.i)
  Define OutputString.s
  OutputString.s = AtomStrings(InputAtom)
  ProcedureReturn OutputString
EndProcedure

;
;     The following macros allow us to declare atoms and use them more easily within PB code.
;     Use atom(thisatom) to declare an atom, which in turn declares and initializes a global variable named _thisatom
;     Any code that's going to use the _thisatom syntax needs to declare with atom() before the first appearance
;     of _thisatom. Never assign to the resultant variable: pretend it's a constant.
;
;     Never use quotes to delineate an atom, either for declaration or actual usage.
;
;     Leading and trailing spaces are stripped, and the atom is stored in lowercase. Do not use atoms for case sensitive contexts.
;
;     While legal characters are alphanumeric, underscores, periods, and forward slash, only use alphanumeric and underscores for
;     atoms declared in code. Periods and slashes will result in a compilation error, and thus should only be used in data-based
;     or run-time generated atoms.
;


Macro AtomQuote     ; Necessary for putting quotes around the atom name in the next macro
  "
EndMacro

Macro atom(atomtext)
  Global _#atomtext.i = newatom(AtomQuote#atomtext#AtomQuote) ; effectively stringtoatom("atomtext")
EndMacro




A lot of the sanity checking is currently absent/incomplete, and this is used as a 'back end' for various other systems (where I need identifiers to be unique across all systems, not just within a system). There's no reason you could adapt this to specific tasks, though, and it works pretty well for it.

This enables you to have things defined at compile time or runtime, with no real need to distinguish between the two in the code that accepts the data.


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Thu May 17, 2012 11:01 pm 
Offline
Addict
Addict

Joined: Sun Dec 12, 2010 12:36 am
Posts: 1284
Location: Waterloo, WI - USA
Wow that Atom concept is really neat!

I wonder if I might be able to do something with it :P

_________________
Image


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Thu May 17, 2012 11:55 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Aug 27, 2011 9:50 pm
Posts: 107
Location: Washington, USA
Zach wrote:
Wow that Atom concept is really neat!

I wonder if I might be able to do something with it :P


You can do a LOT with it. It's one of the core data types in my language. Stolen shamelessly from erlang (although I believe Ruby Symbols are a somewhat similar concept, but used differently).

It's also useful for a kind of 'string compression' when you're using a lot of strings that aren't dynamic, but might be specified at runtime. You can pass around atoms instead. In my compiler, I keep track of what's a string, what's an integer, and what's an atom (among other types, obviously) with a data type field, but data types are actually stored as atoms. :D

Of course, they're still really integers, but with everything in programming, how you use it defines what it is more fully than the low-level properties it may have. You just have to be careful because PB's data typing isn't quite as advanced as something like C, so the PB compiler can't stop and tell you that you attempted to use an 'atom' variable in an 'integer' operation.

This library, or something like it, can be a powerful tool.. But like all powerful tools, be sure you use the appropriate safety gear and follow all precautions appropriate to your environment! :)


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Fri May 18, 2012 5:15 pm 
Offline
Addict
Addict

Joined: Sun Dec 12, 2010 12:36 am
Posts: 1284
Location: Waterloo, WI - USA
Oh yes, I'm sure you can do a lot with it.

I was speaking more to my personal limitations as a novice, who admittedly is not very good at critical-thinking and problem solving when it comes to programming.

_________________
Image


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Sat May 19, 2012 1:39 am 
Offline
Enthusiast
Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
void wrote:
You can do a LOT with it. It's one of the core data types in my language...

Can you give some examples and/or samples? It seems like a lot of overhead, with a global, a string, and a map for every atom.

Thanks.


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Sat May 19, 2012 12:14 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Aug 27, 2011 9:50 pm
Posts: 107
Location: Washington, USA
Tenaja wrote:
void wrote:
You can do a LOT with it. It's one of the core data types in my language...

Can you give some examples and/or samples? It seems like a lot of overhead, with a global, a string, and a map for every atom.


The globals are only for the run-time declared atoms. The map and array of strings don't take up a lot of space, and the version of the library I included resizes the array on demand.

Examples include all of my data type declarations. This allows me to do type validation by checking things against _integer, _float, or _string as essentially enumerations that I don't have to worry about.

I also use this for declaring my keywords, my built-in procedures (called primitives in a forth-alike), and for all user-defined procedures (called words in forth).

These are even useful for string literals compiled into a word; a string gets added to the atom table and replaced with the atom reference. Any future instances of that string are similarly automatically replaced with the same atom reference, so I only have one actual string stored for every instance of a string literal.

Code:
atom(integer)
atom(float)
atom(string)
atom(atom)
; These add those to the atom table, and then when checking data types, I can use _integer, _float, etc in my PB code for the built-in types for my compiler.


; This is used to register simple prim names while also making them   
Define pointer.i
Macro registerprim(primname, pointer)
  atom(primname)
  If Not(FindMapElement(atomtoprimtable(), Str(_#primname)))
    atomtoprimtable(Str(_#primname)) = pointer
    primtoatomtable(Str(pointer)) = _#primname
  Else
    Debug "Redefining prim?"
  EndIf
EndMacro

registerprim(random, @p_random())

; This is a little misnamed, but essentially I use this for prims whose names would create invalid variable names.
; It skips the atom(primname) step, and just creates the atom and registers the prim
Define primatom.i
Macro registerprimunprintable(primname, pointer)
  primatom.i = newatom(primname)
  If Not(FindMapElement(atomtoprimtable(), Str(primatom)))
    atomtoprimtable(Str(primatom)) = pointer
    primtoatomtable(Str(pointer)) = primatom
  Else
    Debug "Redefining prim?"
  EndIf
EndMacro

registerprimunprintable("+", @p_add())


Since it's a generalized solution, I can always turn an atom back into a string without the code having to know whether it was defined at compile time or at runtime. This is very useful for debugging.

Since we can't add it to PB as a first class data type like erlang and ruby (or my language) do, sadly a lot of safety checks are only halfway there. (I do get one check in that if I mistype a _whatever definition, EnableExplicit throws a complaint at me)

Use of atoms as a data type in the compiled code is a more complicated subject, but basically it's the freedom to get something in the same category of enumeration for 'free', and being able to safely define new items whenever you want, and always having a guarantee that within a given execution of the program, there will be no clashes and no duplicates.

Obviously, this isn't useful for everyone, but there's a large category of things for which the concept is a very useful abstraction.


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Sat May 19, 2012 4:18 pm 
Offline
Enthusiast
Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
Very interesting. I have saved it for a rainy day.

BTW, PB only stores a single instance of a literal string also, regardless of how many times it is used.


Top
 Profile  
 
 Post subject: Re: "variable" compiler constant?
PostPosted: Sat May 19, 2012 11:40 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Aug 27, 2011 9:50 pm
Posts: 107
Location: Washington, USA
Tenaja wrote:
BTW, PB only stores a single instance of a literal string also, regardless of how many times it is used.


Yes, but it can't very well do that for a string read in from a file.

I'm talking about string literals in programs compiled by the compiler I'm writing in PB.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye