Giter VIP home page Giter VIP logo

optic-lua-dev's People

Contributors

philiproman avatar

Stargazers

 avatar  avatar

Watchers

 avatar

optic-lua-dev's Issues

Refactor ResultBuffer

The current design is flawed and does not permit correct indentation in some cases, such as function bodies.

Fix and refactor table compilation

The current model is nearly unmaintainable, does not support colon call syntax and has several known bugs. Example:

local a = {
	b = function()
		return {
			c = 5
		}
	end
}
print(a.b().c) -- expected "5" got "table 0x3754a4bf"

Backwards for-range loop not working

For-range loops where start index is greater than end index should behave as if step was -1
For-range loops where step is negative should use ">=" limit comparison instead of "<="

An ideal solution would avoid duplicating the loop body.

Don't translate (x < y) to (not(x >= y))

For floating-point comparisons (x < y) is not the same as not (x >= y) in the presence of NaNs.

Proof:

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> z = 0/0
> =z
-nan
> return z>z
false
> return z<z
false
> return z>=z
false
> return not (z>=z)
true

Add interactive shell

Add the option to launch the compiler as an interactive shell which reads statements line-by-line and compiles each statement before executing.

This would greatly improve the efficiency of debugging the compiler.

Better intermediate representation

The current representation is missing several features:

  • equivalence of expressions
  • clear separation between single values and value lists
  • full type information (not just integer, number or object)
  • clear separation between expressions and statements
  • tree pattern matching

Allow newlines and other escape chars within string literals

"\n" in Lua source code causes a newline character to be written in the Java source during compilation, which then causes a compiler error since Java string literals may not contain newlines. This happens because the parser converts the "\n" within string literals to actual newlines.

Consider using ByteBuffer instead of String

Lua strings are simply arrays of bytes (and often are used to store binary data). Seems like byte buffers would be a better fit for this (and would also allow better low-level manipulations, if necessary).

We have to manually intern the string literals, by storing them as constants.

Speculate which variables are primitive

While we can't assume the type of expressions like f() + g() due to the presence of metatables, we can speculate that variables which use standard operators are primitive and generate a fast path.

Complete Lua standard library

Add missing functions from standard library.

  • assert
  • collectgarbage
  • dofile
  • error (level not implemented)
  • getmetatable
  • ipairs
  • pairs
  • load
  • loadfile
  • next
  • pcall
  • print
  • rawequal
  • rawget
  • rawlen
  • rawset
  • select
  • setmetatable
  • tonumber (base not implemented)
  • tostring
  • type
  • _VERSION
  • xpcall
  • coroutine.create
  • coroutine.isyieldable
  • coroutine.resume
  • coroutine.running
  • coroutine.status
  • coroutine.wrap
  • coroutine.yield
  • require
  • package.config
  • package.cpath
  • package.loaded
  • package.loadlib
  • package.path
  • package.preload
  • package.searchers
  • package.searchpath
  • string.byte
  • string.char
  • string.dump
  • string.find
  • string.format
  • string.gmatch
  • string.gsub
  • string.len
  • string.lower
  • string.match
  • string.pack
  • string.packsize
  • string.rep
  • string.reverse
  • string.sub
  • string.unpack
  • string.upper
  • utf8.char
  • utf8.charpattern
  • utf8.codes
  • utf8.codepoint
  • utf8.len
  • utf8.offset
  • table.concat (sub-range not implemented)
  • table.insert
  • table.move
  • table.pack
  • table.remove
  • table.sort
  • table.unpack
  • math.abs
  • math.acos
  • math.asin
  • math.atan2
  • math.atan (uses a 1-argument atan)
  • math.ceil
  • math.cos
  • math.deg
  • math.exp
  • math.floor
  • math.fmod
  • math.huge
  • math.log (custom base is not implemented)
  • math.max
  • math.maxinteger
  • math.min
  • math.mininteger
  • math.modf
  • math.pi
  • math.rad
  • math.random
  • math.randomseed
  • math.sin
  • math.sqrt
  • math.tan
  • math.tointeger
  • math.type
  • math.ult
  • io.close
  • io.flush
  • io.input
  • io.lines
  • io.open
  • io.output
  • io.popen
  • io.read
  • io.tmpfile
  • io.type
  • io.write
  • file:close
  • file:flush
  • file:lines
  • file:read
  • file:seek
  • file:setvbuf
  • file:write
  • os.clock
  • os.date
  • os.difftime
  • os.execute
  • os.exit
  • os.getenv
  • os.remove
  • os.rename
  • os.setlocale
  • os.time
  • os.tmpname
  • debug.* (can it be implemented?)

Remove dependency on Kotlin

Kotlin is used in just a few places in this project. Removing it will simplify and speed up the build process as well as reduce the size of the shadow jar.

Use simple logging instead of Message API

The original goal of Message API was to implement an error list, but now it has turned into a full-blown (and horrible in terms of maintainability) logging framework. This should be fixed.

Create a FFI interface

FFI interface proposal

Users should be able to manipulate arbitrary Java objects, classes and methods from Lua code as if they were Lua tables and functions. There should also be special functions for operations provided by the language itself which aren't available through standard libraries, like array creation, etc. Example Lua code:

local list = ArrayList.new()
list:addAll {"a", "b", "c"}
print(list:toString())

local sort = Arrays.sort
local array = "Hello, world!".toByteArray()
sort(array)
System.out.write(array)

There should be sensible operators available on the types, for example instances of java.util.Map or java.util.List should support the index access and length operators.

Difficulties

Java allows method overloading and there is no way to correctly choose a single overload in the general case. For example:

local write = OutputStream.write -- write(int) or write(byte[])?

As such, the obtained function is not a direct handle to a specific method, but rather a dynamic dispatch proxy, which will decide which method to call depending on argument types.

Still, there are several cases where it is not possible to determine the function that should be called, such as, for example, Math.round(double) versus Math.round(float). In these cases, the proxy should prefer primitives with larger capacity.

When the argument is null or for any other reason there exists a conflict between overloads, the proxy would be allowed to pick any arbitrary overload.

Alternative

If creating a full FFI interface turns out too difficult, the project should at least support converting a Java method to Lua function by wrapping the method with type adapter code.

Multiple values are not truncated within parenthesis

Essentially, the problem is that the statement:

print(((function() return 1, 2, 3 end)()))

in standard Lua 5.3 prints:

1

whereas in optic-lua it prints:

1   2   3

This doesn't usually cause issues, but it is still non-standard behaviour.

Direct calls to local final functions

An expression in form of f(x, y, ...) where f is a final local (or final upvalue) variable should call the body of f directly. In the ideal case, argument checks could be lifted out of the function.

Create a seperate module containing only runtime API

The build process should produce a Jar that contains only the runtime API classes.

Requirements:

  • Must be Java 1.8-compatible
  • Must not have any external dependencies (or at least make them optional)
  • Must not depend on any classes that are not within the optic.lua.runtime package
  • Must be as small as possible - preferably below 50 KB

Local recursive functions are declared as local AFTER expression evaluation

Test case:

local function fact(n)
  if(n <= 1) then 
    return 1 
  else 
    return n * fact(n-1) 
  end
end

Will currently throw an error because inside the function body, "fact" is considered global.
Note that the next example must NOT work the same way, due to Lua language rules:

local fact = function(n)
  if(n <= 1) then 
    return 1 
  else 
    return n * fact(n-1) 
  end
end

The local x = function() ... end and local function x() ... end are NOT semantically equal - the second notation declares "x" BEFORE evaluating function body!

Optionally link functions at compile-time

There should be an option to bypass hash-table lookup for the standard library. Sample code:

local x = tonumber(io.read()) + 1

Currently would generate this:

Object x = add(call(getglobal("tonumber"), call(index(getglobal("io"), "read"))), 1);

If the user is willing to sacrifice the ability to dynamically replace these functions, we could instead generate code like this:

int x = __tonumber(_ioread()) + 1

A similar mechanism could be used in implementing FFI (#18)

Logical operators are not lazy

local function f()
	return true
end

print(f() or g())

Running the above script causes an error due to trying to call a nil value ("g"). In standard Lua, the script prints "true" because of lazy evaluation. Looking at the generated Java code, it's clear that arguments to logical operators are evaluated eagerly (look below the comment "// line 5")

import optic.lua.runtime.*;
import static optic.lua.runtime.DynamicOps.*;
import static optic.lua.runtime.ListOps.*;
import optic.lua.runtime.invoke.*;
import java.util.Iterator;
public class logic_dlua {
        public static Object[] run(final LuaContext context_v4, Object[] args) { if(1 == 1) {
                final CallSite call_site_vA = context_v4.callSite(4);
                final CallSite call_site_v9 = context_v4.callSite(3);
                final CallSite call_site_v8 = context_v4.callSite(2);
                final FunctionFactory function_factory_v6 = context_v4.functionFactory(1);
                        // line 1
                        final Object L_f;
                        L_f =
                                new LuaFunction(function_factory_v6){ Object[] call(LuaContext context_v7, Object[] argsv5) { if(1==1) {
                                        // line 2
                                        return list(true);
                                } return EMPTY; }}
                        ;
                        // line 5
                        Object v1 = get(call_site_v8.invoke(context_v4, L_f,list()), 0);
                        Object v2 = get(call_site_v9.invoke(context_v4, context_v4.getGlobal("g"),list()), 0);
                        call_site_vA.invoke(context_v4, context_v4.getGlobal("print"),list(((Object)(v1) == null || (Object)(v1) == Boolean.FALSE ? (Object)(v2) : (Object)(v1))));
        } return EMPTY; }
        public static void main(String... args) {
                run(LuaContext.create(), args);
        }
}

Fast table implementation

The current implementation is a naive java.util.HashMap with additional overhead for keeping track of length and max index. A better implementation is needed, preferably with special treatment for numeric keys and values.

Create a proper README

Information in README should include:

  • Brief description
  • Installation instructions
  • Basic usage example
  • Feature list

Reduce jar size

Currently the jar of this project weighs 205 KB, while the full jar with dependencies (which is the one you'd use to run the actual compiler) is 19 MB!

Exceptions when using "function f() ... end"

Typing the following code in interactive shell:

function f() end

results in the following exception:

[main] ERROR optic.lua.io.InteractiveShell - Uncaught error
java.lang.IllegalArgumentException: Line number must be greater than 0
        at optic.lua.asm.Step$LineNumber.<init>(Step.java:216)
        at optic.lua.asm.StepFactory.lineNumber(StepFactory.java:82)
        at optic.lua.asm.MutableFlattener.flatten(MutableFlattener.java:60)
        at optic.lua.asm.MutableFlattener.flatten(MutableFlattener.java:48)
        at optic.lua.io.LuaToJavaCompiler.compile(LuaToJavaCompiler.java:15)
        at optic.lua.io.InteractiveShell.evaluate(InteractiveShell.java:93)
        at optic.lua.io.InteractiveShell.run(InteractiveShell.java:73)
        at optic.lua.Main.main(Main.java:74)

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.