Author Topic: unrecognized function in macro and other issue.  (Read 1242 times)

0 Members and 1 Guest are viewing this topic.

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 699
    • PluriBASIC
Re: unrecognized function in macro and other issue.
« Reply #15 on: August 18, 2020, 09:07:27 pm »
 I would need to know your code better to understand how you are using the colon character. If you have a minute maybe i can tell you what i am doing to avoid exhausting the uses i can give to a word or character.

 I made my engine in a way that any character can be used anywhere and have a different purpose depending on the statement it is working on, its pretty efficient and can parse and convert the whole code in less than 5 seconds (PowerBASIC takes 3.9 so, 1 second more is pretty acceptable).

 My tokenizer first analyzes the code and labels all parts of it. For optimized speed it doesnt actually move data around, it only creates a "dictionary" of words, containing data about what kind of word it is and where in the memory each one is located. This is a pretty fast process, it usually takes like 0.4 seconds even for huge source codes. This process labels every word depending on what it is, %KW_RESERVED, %KW_CRLF... %KW_OPERATOR... %KW_EQUATE... etc. I have currently 177 types of different words.

 After this point, checking strings directly is almost unnecessary, making it pretty fast. It only checks the word type byte (for %KW_XXX values) and an INTEGER value if the byte contains a %KW_RESERVED (for %RW_XXXX values).

 After that, the engine analizes the dictionary and "expands" macros, in a second "expanded" dictionary where all the macros have been expanded and are ready to be evaluated. No words are analyzed during that process, and no strings are moved around, only the dictionary is updated, this makes it pretty fast too.

 Then it goes word by word, and when it finds a %KW_CRLF (or a %KW_COLON or %KW_GBRACKETCLOSE if the previous statement ended with one of those), It then analizes what kind of word is next.

 Suppose after a %KW_CRLF the engine finds a %KW_RESERVED, it then checks what reserved word it is and acts accordingy.

 For example if it finds a %RW_FUNCTION in the dictionary, it invokes:

Code: [Select]
CALL handleModules(DICTIONARY(), Index)
 This analizes the words, and if it is being used to define a function (by finding a %KW_BRACKETOPEN after the name) or if it is being used to return the value of a function (by finding %KW_EQUAL after %KW_RESERVED).

 If it finds a %KW_FREEVAR after the reserved word, it then checks if there is a %KW_BRACKETOPEN, and if so, the bracket count goes up 1 and keeps looking for more code.

 If at one point during this, it finds a %KW_COLON when the bracket count is 1, it "could" (it doesnt right now) be taken as a "special" separator, for name and value.

 Then, if a later point the bracket count is decreased with %KW_BRACKETCLOSE, look if there is an %KW_RESERVED with %RW_EXPORT... then See if there is an %KW_RESERVED with %RW_AS... and then look for a %KW_DATATYPE. After that. It finally expects the end of the statement, it expects either a %KW_GBRACKETOPEN or %KW_COLON or %KW_CRLF.

 During all this, the colon was used for two different purposes depending on what part of the statement it was analizing, so, in theory it would be impossible to exhaust the uses of a colon. It could have hundreds or thousands of uses and it is pretty fast!

 Using this technique, i can use many words for many purposes without exhausting it's uses, for example, i can use the BIT word as follows:

Code: [Select]
STDOUT BIT(var, 1)

BIT SET var, 1

udtmem AS BIT * 4 IN BYTE

 The CPU footprint is small, memory usage is low, and the uses of words are virtually unlimited.

 By the way, if the tokenizer finds a %KW_COLON it checks if the previous found word was also a %KW_COLON, and if so, it converts the previous word in a %KW_NAMESPACESEPARATOR and discards the last %KW_COLON. This makes it easier to work with keywords at a later stage of the compilation.

 This process (along with some clever indexing for huge lists of equates) can beat PowerBASIC's speed under some circumstances and get pretty close to it the rest of the times... all this without using assembly exclusively, so, i now i can optimize it even further by using more assembly in some areas.


« Last Edit: August 18, 2020, 11:19:42 pm by Brian Alvarez »

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4486
    • Oxygen Basic
Re: unrecognized function in macro and other issue.
« Reply #16 on: August 19, 2020, 12:48:11 am »
Thanks Brian,

The o2 compiler has quite a few passes to it including Unicode conversion, translation, assembler and linker. Unlike C, macros are expanded late (on-the-fly).

But what I meant was I did not want to change the grammer regarding colons vs equals sign.

However, this might be useful to you. You can put conditionals and logicals straight into a macro function.

Code: [Select]
'05:28 19/08/2020
'return type flexible using 'any'
macro ifs any(r,c,a,b)
  if c
    r=a
  else
    r=b
  endif
end macro

string s=ifs(1=2, "yes", "no")
float r=ifs(1=2, 1.5, 2.5)
print s " " r

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 699
    • PluriBASIC
Re: unrecognized function in macro and other issue.
« Reply #17 on: August 19, 2020, 01:33:33 am »
Yes, I ended up using almost exactly that (as per your suggestion several months ago, thanks!):

Code: [Select]
macro IIF& long(R,X,A,B)
  if int(x)=0 then
    r = b
  else
    r = a
  end if
end macro

For consistency, I decided to round x because sometimes a floating point value can trigger the true option for irrelevant values. I decided to create one for each data type, i dont recall why but i had a good reason.


Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4486
    • Oxygen Basic
Re: unrecognized function in macro and other issue.
« Reply #18 on: August 30, 2020, 07:01:24 am »
After removing the C-style ternary evaluator from te compiler, the boolean expressions seem to be working okay. But you will need to use '==' instead of '='

This will work in the next release: 0.3.0
Code: [Select]
function iif(int c,a,b) as int
  if c
    return a
  else
    return b
  endif
end function

print iif(1==2, 11, 10) '10


Brian Alvarez

  • Hero Member
  • *****
  • Posts: 699
    • PluriBASIC
Re: unrecognized function in macro and other issue.
« Reply #19 on: August 30, 2020, 09:57:42 am »
Perfect! this will be a good addition. :)

John

  • Hero Member
  • *****
  • Posts: 3966
Re: unrecognized function in macro and other issue.
« Reply #20 on: August 31, 2020, 12:45:31 am »
Quote
After removing the C-style ternary evaluator from te compiler, the boolean expressions seem to be working okay.

I can only imagine how much that simplifies the code. I'm not a fan of inline assignments as arguments to functions.
« Last Edit: August 31, 2020, 12:55:45 am by John »

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4486
    • Oxygen Basic
Re: unrecognized function in macro and other issue.
« Reply #21 on: August 31, 2020, 02:14:13 am »
Even for C the syntax is dirty.