Giter Site home page Giter Site logo

eclipse-archived / golo-lang Goto Github PK

View Code? Open in Web Editor NEW
476.0 65.0 91.0 6.72 MB

Golo - a lightweight dynamic language for the JVM.

Home Page: http://golo-lang.org/

License: Eclipse Public License 2.0

Ruby 0.47% Java 73.74% Golo 24.75% TeX 0.18% Shell 0.13% Dockerfile 0.05% Kotlin 0.68%
golo jvm language invokedynamic programming-language java

golo-lang's Introduction

Continuous integration and deployment DOI Gitter

Golo, a lightweight dynamic language for the JVM.

The world didn't need another JVM language. So we built yet another one. A simple one.

Golo is a simple dynamic, weakly-typed language for the JVM.

Built from day 1 with invokedynamic, Golo takes advantage of the latest advances of the JVM. It is also a showcase on how to build a language runtime with invokedynamic.

Eclipse Golo was originally created by Julien Ponge and developed as part of the research activities of the DynaMid group of the CITI Laboratory at INSA Lyon.

Eclipse Golo is a mature Eclipse Technology Project.

Links

Getting Golo

Golo follows the semantic versioning scheme.

Go to the Golo downloads page for general download instructions.

You can fetch Golo from Maven central under the org.eclipse.golo group.

Building Golo

Dependencies

Golo is built with Gradle. Since the source code contains the Gradle wrapper scripts, the build can bootstrap itself by downloading the qualified Gradle version from the Internet.

Java virtual machine compatibility

Golo requires Java 8 to build. Building beyond Java 8 is currently disabled: at this time Golo is not fully compatible with the changes introduced in Java 9 and the Java Platform Module System.

In practice you can run most Golo code with Java 11 and beyond, but you may see some reflection-related warnings.

Building

Common tasks:

  • build: ./gradlew build
  • test: ./gradlew test
  • clean: ./gradlew clean
  • documentation: ./gradlew asciidoctor golodoc javadoc
  • assemble a working distribution in build/install: ./gradlew installDist
  • generate a nice JaCoCo tests coverage report: ./gradlew jacocoTestReport

The complete list of tasks is available by running ./gradlew tasks.

License

Copyright (c) 2012-2021 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others

This program and the accompanying materials are made available under the
terms of the Eclipse Public License 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0.

SPDX-License-Identifier: EPL-2.0

Contributing

We welcome contributions from the community!

Check the CONTRIBUTING.md file for instructions.

golo-lang's People

Contributors

arfon avatar artpej avatar danielpetisme avatar edreispi avatar flemouel avatar franckverrot avatar jnizet avatar jponge avatar juherr avatar k33g avatar nstouls avatar oehme avatar samueldg avatar yloiseau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

golo-lang's Issues

Multiline strings

A nice feature to have, such as in:

let text = """This is
a multiline
piece of
      text."""

for back to school ... : parser

if, then, ... are keywords, ok. But it would be nice if we could use them as "personal" functions to do something like that :

module verbalexpression

struct verEx = { foo }

augment verbalexpression.types.verEx {
    function find = |z| {
        #foo
    }

    function then = |z| {
        #foo
    }
}

function main = |args| {
    let tester = verEx():find("bob"):then("morane")
}

I do not want to write Then, it's less beautiful than then

Strange behavior in varargs in dynamic object methods when capture needed

Remember https://github.com/golo-lang/golo-lang/pull/68
I tried to make the closure capture an object but it fails:

 module test

function main = |args| {
  let decorator = ">" 

  let o = DynamicObject()
  o: define("fun", |this, args...| {
    println("@fun()")
    foreach arg in args {
      println("  " + decorator + arg)
    }
  })
  o: fun("plop", "da", "plop")
  o: fun("flock", "flock")
  o: fun("flick")
  o: fun()
}
Exception in thread "main" java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(Object,Object[])Object to (Object,Object,Object,Object)Object
    at java.lang.invoke.MethodHandle.asType(MethodHandle.java:691)
    at java.lang.invoke.InvokeGeneric.dispatch(InvokeGeneric.java:103)
    at java.lang.invoke.InvokeGeneric.dispatchWithConversion(InvokeGeneric.java:117)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:162)
    at test.main(test.golo)
    at fr.insalyon.citi.golo.cli.Main.callRun(Main.java:254)
    at fr.insalyon.citi.golo.cli.Main.golo(Main.java:282)
    at fr.insalyon.citi.golo.cli.Main.main(Main.java:155)

Test access_items_from_subclass failing with hotspot build 1.7.0_45-b18

Hi,

There seem to be a problem with the test 'access_items_from_subclass' under hotspot build 1.7.0_45-b18, linux 64bit version, with the latest build b2643b6
The test is the only one to fail, producing the following error :

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
Configuring TestNG with: TestNG652Configurator
>>> 5
Tests run: 317, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 3.289 sec <<< FAILURE!
test_method_invocations(fr.insalyon.citi.golo.compiler.CompileAndRunTest)  Time elapsed: 0.03 sec  <<< FAILURE!
java.lang.reflect.InvocationTargetException: null
    at java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:113)
    at java.lang.invoke.MemberName.getMethodType(MemberName.java:125)
    at java.lang.invoke.DirectMethodHandle.<init>(DirectMethodHandle.java:58)
    at java.lang.invoke.DirectMethodHandle.<init>(DirectMethodHandle.java:47)
    at java.lang.invoke.DirectMethodHandle$StaticAccessor.<init>(DirectMethodHandle.java:439)
    at java.lang.invoke.DirectMethodHandle$StaticAccessor.<init>(DirectMethodHandle.java:432)
    at java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:85)
    at java.lang.invoke.MethodHandles$Lookup.getDirectField(MethodHandles.java:1299)
    at java.lang.invoke.MethodHandles$Lookup.unreflectField(MethodHandles.java:993)
    at java.lang.invoke.MethodHandles$Lookup.unreflectGetter(MethodHandles.java:985)
    at fr.insalyon.citi.golo.runtime.FunctionCallSupport.fallback(FunctionCallSupport.java:100)
    at golotest.execution.MethodInvocations.access_items_from_subclass(method-invocations.golo:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at fr.insalyon.citi.golo.compiler.CompileAndRunTest.test_method_invocations(CompileAndRunTest.java:568)


Results :

Failed tests: 
  CompileAndRunTest.test_method_invocations:568 » InvocationTarget

Tests run: 317, Failures: 1, Errors: 0, Skipped: 0

Commenting it, the rest passes with no errors.

strange bug when string affectation in body of each() method of hashmap (parser?)

import java.util.HashMap

function main = |args| {

let h = HashMap()
    :add("firstName","Bob")
    :add("lastName","Morane")

let s = ""
h:each(|key, value|{
  println(s + key+ " " + value + " ")
})

}

Result : OK

lastName Morane 
firstName Bob 

I try this :

import java.util.HashMap

function main = |args| {

let h = HashMap()
    :add("firstName","Bob")
    :add("lastName","Morane")

let s = ""
h:each(|key, value|{
  println(s + key+ " " + value + " ")
  s = s + key+ " " + value + " "
})

}

Result : KO

Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
pouet.__$$_closure_0(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @0: aload_2
Reason:
Type top (current frame, locals[2]) is not assignable to reference type
Current Frame:
bci: @0
flags: { }
locals: { 'java/lang/Object', 'java/lang/Object' }
stack: { }
Bytecode:
0000000: 2c2a 1248 2b12 48ba 004f 0000 ba00 4f00
0000010: 00ba 004f 0000 ba00 4f00 00ba 0052 0000
0000020: 572c 2a12 482b 1248 ba00 4f00 00ba 004f
0000030: 0000 ba00 4f00 00ba 004f 0000 4d01 b0

at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:68)

I try this :

import java.util.HashMap

function main = |args| {

let h = HashMap()
    :add("firstName","Bob")
    :add("lastName","Morane")

let s = ""
h:each(|key, value|{
  s = s + key+ " " + value + " "
})

}

result : KO

Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
pouet.__$$_closure_0(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @0: aload_2
Reason:
Type top (current frame, locals[2]) is not assignable to reference type
Current Frame:
bci: @0
flags: { }
locals: { 'java/lang/Object', 'java/lang/Object' }
stack: { }
Bytecode:
0000000: 2c2a 1217 2b12 17ba 0022 0000 ba00 2200
0000010: 00ba 0022 0000 ba00 2200 004d 2cb0

at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:68)

I try this :

import java.util.HashMap

function main = |args| {

let h = HashMap()
    :add("firstName","Bob")
    :add("lastName","Morane")

let s = ""
h:each(|key, value| {
  s = key + " " + value + " "
})

println(s)

}

Result : no error, but s is empty

i try this :

import java.util.HashMap

function main = |args| {

let h = HashMap()
    :add("firstName","Bob")
    :add("lastName","Morane")

let s = ""
h:each(|key, value| {
  println(s + key + " " + value + " ")
  s = key + " " + value + " "
})

println(s)

}

Result :
Error again

Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
pouet.__$$_closure_0(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @0: aload_2
Reason:
Type top (current frame, locals[2]) is not assignable to reference type
Current Frame:
bci: @0
flags: { }
locals: { 'java/lang/Object', 'java/lang/Object' }
stack: { }
Bytecode:
0000000: 2c2a 1217 2b12 17ba 0022 0000 ba00 2200
0000010: 00ba 0022 0000 ba00 2200 00ba 002c 0000
0000020: 572a 1217 2b12 17ba 0022 0000 ba00 2200
0000030: 00ba 0022 0000 4d01 b0

at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:68)

Invoke methods on JVM arrays and make them iterable

Golo currently deals with JVM arrays through special functions like aget, aset, etc.

We could improve their manipulation and make them work like other collections such as those from java.util by dealing with them as special receivers on method invocations.

This would allow code like: some_array: get(5) or some_array: iterator(), which could also make arrays directly usable in foreach loops without a prior conversion using atoList().

Build failure on Windows (documentation)

I'm a bit ashamed to report this issue... but yes sometimes I use Windows 😄

[INFO] --- golo-maven-plugin:0-preview10-SNAPSHOT:goloc (goloc) @ golo ---
[INFO] Compiling to: target/classes
[INFO] Compiling: src\main\golo\standard-augmentations.golo
[ERROR] Encountered " <COMMUTATIVE_OPERATOR> "- "" at line 19, column 1.
Was expecting one of:
    "\n" ...
    "module" ...
    <COMMENT> ...
    <DOCUMENTATION> ...

goloc and OperatorSupport : java.lang.NoClassDefFoundError

i compile a golo library : goloc -output classes 42.golo

module org.fortytwo.H2G2

function hello = |name| {
    let r = "Hello " + name
    return r
}

when i use it with java :

System.out.println(hello("Bobby"));

i've got an error :

Exception in thread "main" java.lang.NoClassDefFoundError: fr/insalyon/citi/golo/runtime/OperatorSupport
at org.fortytwo.H2G2.hello(42.golo)
at Main.main(Main.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.ClassNotFoundException: fr.insalyon.citi.golo.runtime.OperatorSupport
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 7 more

Use local functions in augmentations

Local functions cannot be used from augmentations defined from the same module.

Indeed, augmentations and module functions are compiled to different class files, and they would need some access lifting at runtime as they are effectively JVM-private.

See #26

Handle " in template delimiter bounds

Golo templates currently have an issue with code such as:

<a href="<%= plop %>">Plop</a>

because the template splits into strings that have " at their bounds. Combined with the fact that the template engine renders template elements in multiline strings ("""), it yields parser errors.

A fix would be to look at template text substrings, and have special handling when they start and/or end with ".

JVM bytecode debug symbols

The Golo bytecode currently lacks debug informations. This makes it hard to spot the source of, say, an exception as there is no correspondence between bytecode and line numbers in the original Golo source code.

Migrate from Stack to Deque

java.util.Stack is used in many places in the compiler and bytecode generation code. I forgot that it extends the old java.util.Vector.

The code shall be upgraded to user java.util.Deque instead, with a backing java.util.LinkedList implementation.

Impossible to get properly an Array class type

Silly mistake coming from the lexer (I guess).

module array

function main = |args| {
  require(args oftype java.lang.Object[].class, "Should be an array of object")
}

Output

[error] In Golo module: issue-array.golo
[error] Encountered " <COLL_START> "[ "" at line 5, column 39.
Was expecting one of:
    "." ...
    "(" ...

[error] Encountered " "." ". "" at line 5, column 41.
...

Possible workaround

  let array_type = -> java.lang.reflect.Array.newInstance(java.lang.Object.class, 0): getClass()
  require(args oftype ARRAY_TYPE(), "Should be an array of object")

A compiled golo program is launched 2 times

Modus operandi :

file tryme.golo :

module tryme

function main = |arg|{
  println("HELLO")
}

command : golo compile --output tryme_classes tryme.golo

then :

cd tryme_classes
golo run --module tryme

and i get :

HELLO
HELLO

Java 8 lambda interoperability

Java 8 lambdas are being created using java.lang.invoke.LambdaMetafactory.

Golo can already convert functions to SAM interfaces, but full Java 8 lambda interoperability uses a more complex creation process because of, say, default methods.

Strange behavior with a closure named "beforeEach"

I succeed to shrink the beforeEach issue into a test case:
I pass closures as function arguments but if the argument is named beforeEach the code fails. Nevertheless, if you change the arg name it works.

The stacktrace explains that the signature is wrong, in fact during the runtime the beforeEach identifier is mapped to the it and vice-versa (to check it, uncomment the beforeEach & it and comment the current ones).

module weird

local function test = |describe, it, beforeEach| {
  describe("MySuite", {
    beforeEach({
      println("before")
    })
    #beforeEach("False it", { println("before") })

    it("MyTest", {
      println("it")
    })
    #it( { println("before") })
  })
}

function main = |args| {

  let describeFn = |description, specifications| {
    println("Describe " + description + " " + specifications)
    specifications()
  }

  let itFn = |description, fn| {
    println("It " + description + " " + fn)
    fn()
  }

  let beforeEachFn = |fn| {
    println("BeforeEach " + fn)
    fn()
  }

  test(describeFn, itFn, beforeEachFn)
}

Output

Describe MySuite MethodHandle()Object
Exception in thread "main" java.lang.IllegalArgumentException: target and fallback types must match: (MethodHandle,Object,Object)Object != (MethodHandle,Object)Object
    at java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:102)
    at java.lang.invoke.MethodHandles.misMatchedTypes(MethodHandles.java:2263)
    at java.lang.invoke.MethodHandles.guardWithTest(MethodHandles.java:2247)
    at fr.insalyon.citi.golo.runtime.ClosureCallSupport.fallback(ClosureCallSupport.java:79)
    at weird.__$$_closure_0(weird.golo)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.ClosureCallSupport.fallback(ClosureCallSupport.java:81)
    at weird.__$$_closure_3(weird.golo)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.ClosureCallSupport.fallback(ClosureCallSupport.java:81)
    at weird.test(weird.golo)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.FunctionCallSupport.fallback(FunctionCallSupport.java:104)
    at weird.main(weird.golo)
    at fr.insalyon.citi.golo.cli.Main.callRun(Main.java:234)
    at fr.insalyon.citi.golo.cli.Main.golo(Main.java:267)
    at fr.insalyon.citi.golo.cli.Main.main(Main.java:138)

String interpolation

Let's interpole embeded expressions within a String.
Here's a sample test

//Given
let answer  = 42
let what = "answer"

//When 
let sentence = "The ${what: toUpperCase()} is ${answer}"

//Then 
require(sentence == "The ANSWER is 42")

I think the variable interpolation is not that hard (IMHO) where an expresion could be tricky. Maybe we have to split this Specification in 2 (variable & expression)

Regarding the syntax, I dunno care. $ is the historical variable prefix (shell) but any symbol suit fine (Eg. #).

The brackets could be optionnal for variable but mandatory for expressions.

Parser : multiline comments

it would be more practical :

###
 Oh! what a nice comment
 I could write my doc here
 with markdown format
###

Generate a Java compliant main method signature

If a user try to run compiled Golo module with a main method with the Java command , it won't work.

java is looking for a method with the following signature:
public static void main(String[] args)

Golo bytecode generation strategy is the same for all the Golo functions. The bytecode generated for the main is:
public static java.lang.Object main(java.lang.Object)

It would be nice to make Golo main modules 100% Java compliant by generating the appropriate signature for the main method.

String interpolation

String interpolation is a nice feature found in modern languages, such as the following in Ruby:

name = "world"
str = "Hello #{name}!"

ClassCastException at runtime with varargs closure

with this class in Java:

public class JavaObjectArrayMethod {

    public void method(Object[] args){
                //do somthing
    }

}

when i try to invoke this Java method in a Golo varargs parametrized closure return by a function tike this (call1 funtion):

import JavaObjectArrayMethod

function call1 = {
        let javaObject = JavaObjectArrayMethod()
        return |args...| -> javaObject: method(args)
}

function call2 = {
        return |args...| {
                let javaObject = JavaObjectArrayMethod()
                javaObject: method(args)
        }
}

function call3 = {
        let javaObject = JavaObjectArrayMethod()
        return |args| -> javaObject: method(args)
}



function main = |args| {
        let function1 = call1() # fail ( ClassCastException: cannot bind class JavaObjectArrayMethod argument to parameter #1 of (Object,Object[])Object )
        let function2 = call2() # works
        function2("test","test")
        let function3 = call3() # works
        function3(Array("test","test"))

}

( ClassCastException: cannot bind class JavaObjectArrayMethod argument to parameter #1 of (Object,Object[])Object ) is thrown.

Dynamic code evaluation

It would be useful to provide a shortcut (think the evil eval()) to dynamically load code from:

  1. strings,
  2. files.

Extend asInterfaceInstance to multi-methods interfaces

Curently the asInterfaceInstance native function allow to convert a lambda expression to an anonymous implementation of a single method interface.
http://golo-lang.org/documentation/next/#_closures_to_single_method_interfaces

It would be nice to have suh feature for multi-methods interfaces.

Regarding the syntax, Groovy allow to duck type a map to as an interface anonymous impl. Golo provides a DynamicObject which could be used for this issue.

let myList = DynamicObject():
  add(|this, element| -> println(I'm addin stuff): 
  asInterfaceInstance(java.util.List.class)

Or it could be part of the Predefined functions

let myList = asInterfaceInstance(java.util.List.class, DynamicObject():
  add(|this, element| -> println(I'm addin stuff))

My concern was to use Golo to create a FileVisitor implementation http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileVisitor.html

golodoc

The language should provide a dedicated syntax for API documentations.

I propose a notation such as:

----
Integer and string concatenation. This is *awesome*.

- `a` must be some number
- `b` must be a string

It returns the concatenation of `a` and `b`, as a string.
----
function concat = |a, b| -> a + b

The nice thing is that documentation could be written in Markdown, and that the special ---- delimiters could only apply to function, module, augment or any upcoming top-level declaration.

---- is inspired by blocks in AsciiDoc.

The parser could enforce that, meaning that # is for comments while ---- is for documentation.

See #1

Provide an enVironment Manager tool

As POC I've made the govm (stands fo Golo enVironment Manager). The tool is a fork + sed 's/gvm/govm/g' of the gvm tool.

I think an enVironment Manager would be a great killer feature for golo adoption, so it should be managed though the official Github account.

Now, regarding the implementation
govm, gvm client side is obsviously do in shell (compliant bash & cygwin). For server side Vert.x + mongoDB (currenlty hosted on heroku). I ask to the gvm manager if it would be possible to have an environment manager techno agnostic (xvm). Adding a custom wrapper on top of it.

@jponge proposed jenv (inspired by rbenv). The installation seems a bit harder. I dunno how the backend is managed.

So basically we have to choose:

  • the hosting behavior (heroku, cloudbees, custom?)
  • a basic tool to reuse (gvm/jenv)

Bash completion

Bash completion for the golo command line interface would be very useful.

Subscript operators for collections

Long live collection literals!!! Next improvement could be subscript operators cause they are so handy!

There is a Spec:

let list = [1, 2, 3]
require(list[0] is 1)
require(list[1] is 2)
require(list[3] is 3)

let map = [["a", 1], ["b",2]]
require(map["a"] is 1) 
require(map["b"] is 2) 

What's youre thoughts on that?

control flow: case \n generates error

ie : newline after when generates error

case {
    when macouleur is "orange" {
        println("good!")
    }

    otherwise {
        println(":(")
    }
}

generates :
[error] Encountered " "\n" "\n "" at line N, column M.
Was expecting one of:
"when" ...
"otherwise" ...

Maven incremental compilation

The Golo Maven plugin recompiles everytime it is being invoked. We could improve it by making it incremental. Data comparisons should be enough because Golo is a dynamic language, and there is no cross-module check at compile time.

Helpers for incremental compilers

as I am implementing automatic Golo compilation in GLDT, I need to implement incremental compilation. In order to do it, I need get from the Golo file name the name of the generated files. The current Golo compiler exports compilation results as a separate object which is fine but the mapping from this compilation result to the corresponding target file is hidden into the Golo compiler. Would it be possible to export a function/method that exposes it to the outside world ?

DynamicObject and "define" or named method

this sample runs well

module dyno

function Human = |firstName, lastName| {

    return DynamicObject()
    :firstName(firstName)
    :lastName(lastName)
    :toString(
        |this|-> 
            this:firstName()+" "+this:lastName()
    )
    :sayHello(
        |this, message|-> 
            println(message + " from " + this:toString())
    )   
}

function SuperHero = |firstName, lastName, heroName, power|{
let human = Human(firstName, lastName)

return DynamicObject()
    :mixin(human)
    :name(heroName)
    :power(power)
    :define("toString",
        |this|-> 
            this:firstName()+" "+this:lastName()+" aka "+this:name()+" power : "+this:power()
    )
}


function main = |args| {

let clark = SuperHero("Clark", "Kent", "SuperMan", "flying")

clark:sayHello("Hello World!")

}

but if i use a named method instead using define :

    :toString(
        |this|-> 
            this:firstName()+" "+this:lastName()+" aka "+this:name()+" power : "+this:power()
    )

it fires an error :

Caused by: java.lang.IllegalArgumentException: toString must have the following signature: (Object,Object)Object (found: (Object)Object)

gololang.DynamicObject can't be pimped

The golo provided DynamicObject object can't be pimped. I know, I know it may sounds silly to dinamically add a method to a dynamic object. This the use case:

module test


pimp java.util.ArrayList {
  function dump = |this| -> this: each(|it| -> println(it))
}

pimp gololang.DynamicObject {

  function dump = |this| {
    this: properties(): each(|prop| {
      println (prop: getKey() + " -> " + prop: getValue())
    })
  }
}


function main = |args| {
  let  list = java.util.ArrayList()
  list: add(0)
  list: add(1)
  list: dump()

  let mrbean = DynamicObject():
  name("Mr Bean"):
  email("[email protected]"):
  toString(|this| -> this: name() + " <" + this: email() + ">")

  mrbean: dump()
}

and there you have the stack

0
1
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:69)
Caused by: java.lang.NoSuchMethodException: Missing DynamicObject definition for dump
    at gololang.DynamicObject.propertyMissing(DynamicObject.java:151)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.installDynamicObjectDispatch(MethodInvocationSupport.java:201)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:159)
    at test.main(test2.golo)
    ... 5 more

The stack clearly shows that the DynamicObject is trying to handle the dump method (invoking gololang.DynamicObject.propertyMissing)

It could be an understandable limitation of the language.

Partial boolean evaluation

The current implementation of the binary boolean operators and and or evaluates the full expression.

This means that an expression such as:

(foo isnt null) and (foo: bar())

should raise a NullPointerException when foo is null.

Instead, such operators should evaluate each sub-expression in order, and have conditional branching to deal with it. This requires special handling at the AST / IR representation level (rewriting the AST or IR with if statements is a possibility).

Bug with recursive closure invocation

There is a bug in the code generation when recursive calls are being made on closures, such as:

module hello

function main = |args| {
  let fun = |n| {
    println(n)
    fun(n + 1)
  }
}

The problem is that the fun reference loading needs a partial application of fun itself. The generated bytecode is incorrect and breaks the verifier rules (here, a bogus ALOAD_1.

A potential fix is to rewrite such recursive calls as function calls, and remove the function name from the captured references.

List#sort() clash in Java 8

The standard augmentations contain sort(). Java 8 is adding this method, too, hence we need to rename it to avoid clashes.

This causes test failures in gololang.StandardAugmentationsTest when run under a recent build of OpenJDK 8:

  • list_sort
  • list_sort_reverse
  • list_sorted
  • list_sorted_reverse

OSGI bundles for golo

As i'm preparing next iteration for GLDT (Golo Eclipse), I noticed that the Golo jars on Central are not OSGI compliant. This would be nice is this will be available

"".format()

i've found strange behaviour :

println("%s %s":format("5.0","2.0")) #5.0 2.0
println("%s %s":format("5.0",2.0))  #5.0 2.0

println("%s %s":format(5.0,2.0)) #ouch

Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:69)
Caused by: java.lang.NoSuchMethodError: class java.lang.String::format
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.findTarget(MethodInvocationSupport.java:277)
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
at test.main(test.golo)

println(" %s ":format("5.0"))

Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:69)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at fr.insalyon.citi.golo.runtime.TypeMatching.canAssign(TypeMatching.java:62)
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.findMethodOrField(MethodInvocationSupport.java:365)
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.findTarget(MethodInvocationSupport.java:243)
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
at test.main(test.golo)

println("%d %d":format(5.0,2.0)) #ouch

Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:69)
Caused by: java.lang.NoSuchMethodError: class java.lang.String::format
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.findTarget(MethodInvocationSupport.java:277)
at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
at test.main(test.golo)

etc. ...

newWithSameType pimp function implementation is not 100% safe

Currently most of the Collections/functional function pimps are based on the newWithSameType function. The function name is quite explicit but during the runtime we can face some disturbing issues. Indeed, some "Types" are not accessible for instanciation. Private inner classes for instance, such as java.util.HashMap$EntrySet . It's a private implementation of the Set interface.
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java

There is a usecase based on the now famous Mr. Bean....

module test

local function mrbean = -> DynamicObject():
  name("Mr Bean"):
  email("[email protected]"):
  toString(|this| -> this: name() + " <" + this: email() + ">")

function main = |args| {

  let bean = mrbean()
  println(bean: toString())

  bean: email("[email protected]")
  println(bean: toString())

  println("Displaying all the properties")
  println(bean: properties())
  println(bean: properties(): getClass())
  println(bean: properties(): filter(|it| -> it: getKey() == "name"))

}

and there you have the statck:

Mr Bean <[email protected]>
Mr Bean <[email protected]>
Displaying all the properties
[[email protected], name=Mr Bean, toString=MethodHandle(Object)Object]
class java.util.HashMap$EntrySet
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at fr.insalyon.citi.golo.cli.MainGoloGolo.main(MainGoloGolo.java:69)
Caused by: java.lang.InstantiationException: java.util.HashMap$EntrySet
    at java.lang.Class.newInstance0(Class.java:359)
    at java.lang.Class.newInstance(Class.java:327)
    at java.lang.invoke.MethodHandleImpl$BindCaller$T/24300697.invoke_V(MethodHandleImpl.java:1404)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
    at gololang.StandardPimps$java$util$Collection.newWithSameType(standard-pimps.golo)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
    at gololang.StandardPimps$java$util$Set.filter(standard-pimps.golo)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:566)
    at fr.insalyon.citi.golo.runtime.MethodInvocationSupport.fallback(MethodInvocationSupport.java:176)
    at test.main(test1.golo)
    ... 5 more

So basically I'm trying to invoke the filter pimp to get only the "name" property (the original use case was to filter closures w/ isClosure). The filter pimp try to create a fresh instance of java.util.HashMap$EntrySet but it can not and BAZINGA!!

I don't think it could be consider as a language limitation since the behavior is unpredictable. We're not responsible of the implementation underneath an interface.
Of course, we could imagine setting up some reflection voodoo to be able to instantiate a private class but the SecurityManager policies won't help us to do so....
Maybe the easiest solution could be to define some default types which will be use instead of the original one if we"re not able to access/instantiate it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.