Oxygen Basic

Programming => Problems & Solutions => Topic started by: Brian Alvarez on August 16, 2020, 10:37:11 AM

Title: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 16, 2020, 10:37:11 AM
 Hello Charles, im trying to overcome the fact that i cannot place comparisons directly as the parameter of a function. For example, this is not allowed by Oxygen:

Code: [Select]
function isequal(int *c) as long
    return c
end function

print isequal("a" = "b")

Using this is allowed though:

Code: [Select]
print isequal(("a" = "b"))
But then it creates the same issue (when using functions) that I explain next. The problem is in the following code:

Code: [Select]
function something(string s) as string
    return "I exist!"
end function

MACRO testbyte int(r, v  b)
    int b = (v)
    'code to determine the value of r goes here.
    r = b
END MACRO

print testbyte(something("a") = "A")

Complains like this:

Code: [Select]
ERROR: Linker found unidentified names:
1074 something "main source

What i understand is that it does not recognize something as a valid function name... but it IS valid.

If i change the macro like this:

Code: [Select]
MACRO testbyte int(r, v)
    r = v
END MACRO

I expect the macro to place a false or true value in r, depending on the result of a comparison, but instead i get this compile-time error:

Code: [Select]
ERROR: ERROR: parameters mismatch for procedure something
params given : #string#string@00

OPTIONS:
something(string) returns string


WORD: "A"
LINE: 1072
FILE: "main source

It seems to "think" i passed two strings as parameters of something (kind of like a class property method), when in fact i just tried to compare them.

Changing the macro like this:

Code: [Select]
MACRO testbyte int(r, v)
    r = (v)
END MACRO

Goes back to:

Code: [Select]
ERROR: Linker found unidentified names:
1072 something "main source




Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 16, 2020, 10:53:27 AM

Same thing happens with native features:

Code: [Select]
MACRO testbyte int(r, v)
    r = v
END MACRO

print testbyte((lcase("a") = "a"))
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 16, 2020, 11:06:36 AM

This is the issue i was talking about in the first post of this thread:

Code: [Select]
function testbyte (int v) as long
    return v
END function

print testbyte((lcase("a") = "a"))

Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 16, 2020, 12:10:04 PM
Horrible code!. Imagine someone trying to comprehend this code in a large script.

You will always need to enclose the logical expression parameter inside brackets.

This works with 0.2.9

Code: [Select]
function testbyte (int v) as int
return v
end function

print testbyte( ( lcase("A") = "a") )

Title: Re: unrecognized function in macro and other issue.
Post by: JRS on August 16, 2020, 03:48:53 PM
I gave the testbyte example a try in ScriptBasic and it returned a TRUE (-1) result.

Code: Script BASIC
  1. FUNCTION testbyte(c)
  2.   testbyte = c
  3. END FUNCTION
  4.  
  5. PRINT testbyte(LCASE("A") = "a"), "\n"
  6.  


C:\ScriptBASIC\examples>sbc testbyte.sb
-1

C:\ScriptBASIC\examples>



This simplified version returns the same result.

Code: Script BASIC
  1. PRINT LCASE("A") = "a", "\n"
  2.  

Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 16, 2020, 05:35:21 PM
Horrible code!. Imagine someone trying to comprehend this code in a large script.

 I agree is not very nice, unfortunately it is required for the new feature i am working on, otherwise  I would
need to split all the statements myself and would end up being worse for the comprehension in large scripts.

 The new feature is custom operators. Its almost done.
Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 17, 2020, 05:34:12 AM
The brackets are mainly required to distinguish logical expressions from o2's html-like default param setting. For example:

DrawCube( size=2.5, color=red)
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 17, 2020, 01:05:53 PM
Charles, does this mean the order of the parameters can be changed?
Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 17, 2020, 05:50:27 PM
Yes.

Code: [Select]
function drawcube(int color=0,int size=1)
print color " " size
end function

drawcube( size=2, color=0xff) '255 2
Title: Re: unrecognized function in macro and other issue.
Post by: JRS on August 17, 2020, 07:54:02 PM
I'm confused. Are you trying to set an argument variable with a constant before passing it? Why not just pass the constant?

I've always thought FUNCTION argument variables were 'placeholders' and not a reference to other variables with the same name. Is this unique to O2?
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 17, 2020, 09:08:07 PM
John, this is the way some modern languages work. Have you tried swift? Check this out: https://docs.swift.org/swift-book/LanguageGuide/Functions.html

Charles, how does one know what parameters were passed to the module? Also, it would be nice if this behavior was like this:

Code: [Select]
drawcube(size:2, color:0xff) '255 2
 That way you could still use functions like:

Code: [Select]
print iif(answer=correct, "YES", "NO")
 Also it is a little more common to see it like this. I didnt know oxygen had this super power!! Kudos!

 Just my 2 cents.
Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 18, 2020, 12:47:00 AM
Unfortuntely, we have exhausted the uses of the colon in BASIC.

Code: [Select]
drawcube(size:2, color:0xff) '255 2
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 18, 2020, 02:45:18 AM
What does using a colon do?
Title: Re: unrecognized function in macro and other issue.
Post by: JRS on August 18, 2020, 09:17:41 AM
Quote
John, this is the way some modern languages work. Have you tried swift?

I just pass an associative array if I need named arguments in a function.

Thanks for the clarification!
Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 18, 2020, 07:32:51 PM
The colon is primarily used as a statement separator, but is also used for labels, and namespaces, so I would not want to use it as an assignment operator as well.
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez 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.


Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge 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
Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez 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.

Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge 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

Title: Re: unrecognized function in macro and other issue.
Post by: Brian Alvarez on August 30, 2020, 09:57:42 AM
Perfect! this will be a good addition. :)
Title: Re: unrecognized function in macro and other issue.
Post by: JRS 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.
Title: Re: unrecognized function in macro and other issue.
Post by: Charles Pegge on August 31, 2020, 02:14:13 AM
Even for C the syntax is dirty.