Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Support for native calls in flix. #428

Merged
merged 6 commits into from May 8, 2017

Conversation

FlaminGuy
Copy link
Contributor

Apart from discussions in #410 there are couple of other issues:

  1. I'm not quite sure why def f: Bool = unsafe native field java.lang.Boolean.TRUE fails at invoking in Linker.scala
  2. Is there a way to call void functions like the following:
    def f: Bool = let x = unsafe native new java.util.BitSet(); unsafe native method java.util.BitSet.set(x, 1); true
    I also tried let y = unsafe native method java.util.BitSet.set(x, 1); but this tries to pop an object off the stack so this fails.
  3. Every field with _ in it fails at parsing stage
  4. There is no way currently to fetch fields of an object. Looking at NativeField, no object is provided so only static field codes can be emitted.

This allows users to call constructors, methods and fields by using unsafe native new/method/field.
Currently an overloaded native method cannot be called in flix. Discussions about this can be found at flix#410
Tests has been added for this feature.
@magnus-madsen
Copy link
Member

Great! I will take a look soon. Good points about the unsupported features.

val name = method.getName
val descriptor = asm.Type.getMethodDescriptor(method)
// If the method is static, use INVOKESTATIC otherwise use INVOKEVIRTUAL
val invokeCode = if (Modifier.isStatic(method.getModifiers)) INVOKESTATIC else INVOKEVIRTUAL
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us call this invokeInsn,

// Native Static Field //
/////////////////////////////////////////////////////////////////////////////
@test
def nativeCall04: Bool = assertEq!(unsafe native field java.lang.Character.BYTES, 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativeField01

// Native Constructor //
/////////////////////////////////////////////////////////////////////////////
@test
def nativeCall01: Bool = assertEq!(unsafe native new java.lang.String(), "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativeNew01 or nativeConstructor01

// Native Static Methods //
/////////////////////////////////////////////////////////////////////////////
@test
def nativeCall08: Bool = assertEq!(unsafe native method java.lang.Integer.bitCount(2), 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativeMethod01

@magnus-madsen
Copy link
Member

The code looks good to me, modulo a few renamings of test cases. As for your comments:

@magnus-madsen
Copy link
Member

I'm not quite sure why def f: Bool = unsafe native field java.lang.Boolean.TRUE fails at invoking in Linker.scala

Can you post the exception or describe how it fails? If you think the bug is outside your code, you can open a new ticket.

Is there a way to call void functions like the following:
def f: Bool = let x = unsafe native new java.util.BitSet(); unsafe native method java.util.BitSet.set(x, 1); true
I also tried let y = unsafe native method java.util.BitSet.set(x, 1); but this tries to pop an object off the stack so this fails.

I don't understand. Do you mean functions that "return" void?

Every field with _ in it fails at parsing stage

I created #429.

There is no way currently to fetch fields of an object. Looking at NativeField, no object is provided so only static field codes can be emitted.

Good point. I created #430.

@FlaminGuy
Copy link
Contributor Author

I fixed everything in your review.
As for def f: Bool = unsafe native field java.lang.Boolean.TRUE I get:
Exception in thread "main" java.lang.NoSuchFieldError: TRUE at Root.f(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at ca.uwaterloo.flix.runtime.Linker$$anon$2.invoke(Linker.scala:63) at ca.uwaterloo.flix.runtime.Solver$$anonfun$4$$anonfun$apply$3.apply(Solver.scala:742) at ca.uwaterloo.flix.runtime.Model.getConstant(Model.scala:69) at ca.uwaterloo.flix.runtime.Model.getConstant(Model.scala:72) at ca.uwaterloo.flix.Main$$anonfun$2.apply(Main.scala:126) at ca.uwaterloo.flix.util.Timer.<init>(Timer.scala:28) at ca.uwaterloo.flix.Main$.main(Main.scala:126) at ca.uwaterloo.flix.Main.main(Main.scala)
I'm not sure that it is unrelated but I think it's a case. What do you think? (I just run this function in .flix file outside of any testsuite).
And yes, I mean functions which return void. Is there a way to call them?

@magnus-madsen
Copy link
Member

I think it is a type/boxing issue.

I would expect that java.lang.Boolean.TRUE returns an object (i.e. a boxed boolean), but probably the inferred type is primitive boolean (due to the annotation: Bool) hence it cannot find a field of type primitive boolean. You can try --Xdebug to see what bytecode is emitted.

I wonder what would be a good solution to this.

@magnus-madsen
Copy link
Member

If a method has a void return type then push the unit value on the stack.

When a void method is called, we put a Unit object on top of the stack.
A test case for this feature has been added.
@magnus-madsen magnus-madsen merged commit 5236082 into flix:master May 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants