Author Topic: compile/call  (Read 4447 times)

0 Members and 1 Guest are viewing this topic.

pber

  • Guest
compile/call
« on: June 21, 2014, 06:50:57 AM »
hi charles,
i'm writing some test functions that make use of compile/call

assert quote -- mid("123",1,1) = "1"  --
assert quote -- "1" = mid("123",1,1)  --

the 2nd row crashes.
The code evaluated is something like

Code: [Select]
    basic
    if not ( "1" = mid("123",1,1) ) then
        assertErr=-1
    end if

Charles Pegge

  • Guest
Re: compile/call
« Reply #1 on: June 21, 2014, 07:25:03 AM »
Hi Paolo, Can you give more details?

pber

  • Guest
Re: compile/call
« Reply #2 on: June 21, 2014, 07:46:47 AM »
hi Charles,

it seems it crashes only when printing a string.
The initial code I used was similar to this one

Code: [Select]
int assertError=0
string src= quote ||

if not ( "2" = mid("123",2,1) ) then
  assertError= -1
endif
||

sys p= compile(src)
call p

print assertError
print "ok"

the print with assertError pass,
the one with "ok" generates gpf

Now I worked around this problem by assigning
the 2 values to be compared to 2 different sys vars,
then testing. This way the problem does not occur.


.

pber

  • Guest
Re: compile/call
« Reply #3 on: June 21, 2014, 07:57:30 AM »
...my mini-asserts have some problem with UDF

this does not work:

Code: [Select]
function mySqrt(int n)
  return sqrt(n)
end function

assertEQ "3" , "mySqrt(9)"

pber

  • Guest
Re: compile/call
« Reply #4 on: June 21, 2014, 08:26:52 AM »
oh... code evaluated by compile
does not see outer functions, only variables  :(

Charles Pegge

  • Guest
Re: compile/call
« Reply #5 on: June 21, 2014, 09:09:32 AM »
There is a simple workaround for most things :)

The solution is to use a vectored function, wherebye the function address is stored in a variable, which is visible to your dynamic code.

declare *foo()
@foo=@foofun


Code: [Select]
function foofun() as sys, label
===============================
print "foo!"
end function

declare *foo()
@foo=@foofun

function DynExec(string src)
============================
sys    c=compile src
string er=error
if er then
  print "DynExec:" er
else
  call c
end if
freememory c
end function

DynExec "foo()"

pber

  • Guest
Re: compile/call
« Reply #6 on: June 22, 2014, 02:30:07 AM »
Great!

What does label mean?
Code: [Select]
...
function foofun() as sys, label
...
Your example works even without it.

Your example implies the compiled code must use a different syntax
(i.e. function names in compiled code are different
from the "production" code).

Oxygen does not implement namespace, and scope is anonymous.

Maybe I could implement a module-system like this:
Code: [Select]
' here i want to be sure that functions
' are still callable (even if not exported outside the module)
sub worker_function()
  print "I'm just an anonymous worker"
end sub

function entry_function() as sys ', label
  worker_function
end function

type fun_module
    sys (* f1)()
   
    ''''''''''''''''''''''''''
    ' next 2 do not work (...don't they declare a name?)
    'declare *f1() as sys
    '! * f1() as sys
end type

' declare and initialize module <fun>
dim fun as fun_module
@fun.f1= @entry_function


function DynExec(string src)
============================
sys    c=compile src
string er=error
if er then
  print "DynExec:" er
else
  call c
end if
freememory c
end function


DynExec "fun.f1()"

Do exist a better way?

Charles Pegge

  • Guest
Re: compile/call
« Reply #7 on: June 22, 2014, 03:48:49 AM »
Dynamically compiled code has the same syntax as statically compiled code, though there are constraints on the visibility of host functions variables. It's somewhat like a DLL.

OxygenBasic does not have namespaces but scopes are available to confine visibility, without requiring procedures.

sys a=42
scope
  sys a=24
  print a '24
end scope
print a '42


Procedures can also be defined inside procedures, if you need to confine them.

Code: [Select]
function f(sys a,b) as sys
  sys c=45
  '
  function g() as sys
  return a+b+c
  end function
  '
  return g()
end function

print f 100,200 'result 345

Charles Pegge

  • Guest
Re: compile/call
« Reply #8 on: June 22, 2014, 10:23:23 AM »
Not to forget classes as the optimal construct for encapsulation:

Code: [Select]
class fruit
===========

sys skin,flesh,seed

method juice()
print "Juice!"
end method

end class

fruit apple
fruit.juice()

Peter

  • Guest
Re: compile/call
« Reply #9 on: June 22, 2014, 12:22:19 PM »
Quote
class fruit

Hi Charles
Is a joke, isn't it  ;D



.

Charles Pegge

  • Guest
Re: compile/call
« Reply #10 on: June 22, 2014, 12:44:54 PM »
Oh, deadly serious :)

Classes  and their methods are directly visible to dynamically compiled code. No need to setup a vectored function as above:

Code: [Select]
class fruit
===========

sys skin,flesh,seed

method juice()
print "Juice!"
end method

end class


function DynExec(string src)
============================
sys    c
c=compile src
string er=error
if er then
  print "DynExec:" er
else
  call c
end if
freememory c
end function

DynExec "fruit pear : pear.juice" 'Juice!

« Last Edit: June 22, 2014, 12:52:29 PM by Charles Pegge »

pber

  • Guest
Re: compile/call
« Reply #11 on: June 22, 2014, 02:33:01 PM »
Right: using class make things simpler.
thanks Charles.

JRS

  • Guest
Re: compile/call
« Reply #12 on: June 22, 2014, 05:23:11 PM »
Quote from: Peter
Is a joke, isn't it

Oops, no joke.


pber

  • Guest
Re: compile/call
« Reply #13 on: June 23, 2014, 12:38:14 AM »
Oxygen is not a joke.
Without tests i'm not able to move one step ahead,
using classes and objects do not make things easier.

...i feel like they do just what they want, not what i say to do