Code Monkey home page Code Monkey logo

agora's Introduction

The agora programming language

Agora is a dynamically typed, garbage collected, embeddable programming language. It is built with the Go programming language, and is meant to provide a syntactically similar, loose and dynamic companion to the statically typed, machine compiled Go language - somewhat like Lua is to C.

Installation

go get -t github.com/PuerkitoBio/agora/...

This will install the agora packages as well as the agora command-line tool. See agora -h for help, provided the $GOPATH/bin path is in your exported path. The -t flag installs the test dependencies, it works only on Go 1.2 and later, omit it otherwise.

Example

Much more examples are available in the wiki and the source code under /testdata/src, but to give a taste of the syntax, here is the mandatory hello world:

// Output: Hello, Agora !
fmt := import("fmt")
func greet(name) {
	fmt.Println("Hello,", name, "!")
}
greet("Agora")

A few things to note:

  • It looks very similar to Go, minus the types.
  • import is a built-in function, not a keyword. This is important with dynamically-loaded modules, it gives you control of where this overhead of loading and compiling the code is done. It returns the value exported by the module - in this case, an object that exposes methods like Println.
  • Obviously, since this is a dynamically-typed language, arguments have no types.
  • := introduces a new variable. Using an undefined variable is an error, so this statement could not have been =.
  • Statements are valid in the top-level (module) scope. That's because a module (the name for an agora file) is an implicit (top-level) function.
  • Semicolons are managed just like in Go, so although they are inserted in the scanning stage, they are optional (and usually omitted) in the source code.

Resources

Changelog

v0.2.0 / 2013-10-08

v0.1.0 / 2013-09-17

License

Agora is licensed under the BSD 3-Clause License, the same as the Go programming language. The full text of the license is available in the LICENSE file at the root of the repository.

agora's People

Contributors

mna 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

agora's Issues

Better way to detect bytecode files

Currently, bytecode.IsBytecode() only works for io.ReadSeeker types, but the Ctx.Load() can only guarantee an io.Reader. Other way to do this?

v0.1 TODO list

  • Run simple code
  • Call a Goblin function
  • Call native Go function from Goblin
  • Looping constructs
  • Clean printing of VM's state for debugging
  • Table/object type
  • Call methods on object, support for no-such-method
  • Access global variable (outside current func scope)
  • Support for the this keyword, bound to object
  • Refactor native functions/stdlib as objects?
  • arguments[] array to access all received arguments
  • Add K values to DUMP instructions, as comments
  • Bytecode compiler command-line
  • Dynamic loading of .goblin source files (and/or compiled bytecode)
  • Test file that runs all .goblin test data and compares output to expected
  • Syntax
  • Lexer
  • Parser
  • Module/package support (import "user/library")
  • Code generation
  • Ternary operator (?:)
  • Refactor Ctx.Load() by returning only the compiled Module, and have Module.Run() (Val, error) to execute it. Pass the ctx in the constructor of the module (and to each function's constructor).
  • Call a specific Goblin function from Go (get any *Func, possibly based on name?)
  • Make import a built-in function, not a keyword (so import can happen in an if, for example)
    Example: mod := import("dir/sub/mod")
  • Exception/error handling (https://draftin.com/documents/117086)
  • Make a debug built-in function or keyword, that takes a number as argument, to generate a DUMP (then debug the ternary operator bug for test file 19)
  • len() builtin, returns the number of items in an object if it is an object, the length of the string representation of the value otherwise
  • Make assignment to builtins/keywords fail
  • Cyclic dependencies don't work anymore now that Ctx.Load doesn't Run the modules
  • Support standard for loop (for i := 0; i < 10; i++)
  • test use as script in #!
  • Stdlib
  • Emitter tests to validate statements generation (i.e. an if, if else, func within a func within a func, etc.)
  • A complex-ier implementation of an agora program (a JSON parser/stringifier)
  • Finalize stdlib tests
  • Finalize stdlib docs
  • Review all docs, comments for godoc.org

Docs:

  • Internals + Native API on godoc
  • Readme with changelog, quick start, short example, links to docs, to contributing, and license
  • Wiki for language docs by version (ie: all pages for v0.1, then copy for v0.2, ...): installation/Getting started (detailed), similarities & differences vs Go, language reference, VM opcodes, roadmap, stdlib, known bugs (with links to issues), how to write native modules
  • Blog post to announce it

Beyond v0.1

  • Built-in or keyword to get type of variable's value (a.(type) would be nice) is conv.Type(val)
  • Decide what to do with numbers (most probably keep only Float)

v0.2?
Short-circuiting && and ||
Support func(){}() syntax (anonymous immediately-invoked func expression)
Closures (even required for simple cases like calling a func declared in the module, because the module itself is a function, so it needs to close over those funcs - see 46-json.agora)
Coroutines support
Range over whatever (for ... := range) using coroutine (range prepares the coro for execution and iterates it)

v0.3?
Prototype/metamethods support, get inspiration from Lua (http://tylerneylon.com/a/learn-lua/) or JS or a more Go-like approach using embed or something?
Review the this behaviour
Literal array notation, created as Object (like Lua)
i.e. ar := [10, "test", false]

Comma-separated lists in assignment statements (:=, = only)
switch statement
multiple return values

Beyond?

  • Provide an implements built-in to check if an object provides the required fields? Kind of built-in duck-typing, a-la my implements.js library?
  • Remove the need for return nil to be added by the parser?
  • Much better compiler error messages
  • Better errors in general (VM)
  • Check limits (i.e. 2^48 for instruction's value, etc.)
  • Refactor compiler
  • REPL
  • Optimizations
  • Debugger

Raw string notation in assembly code

The raw string notation is supported in the source code (backtick strings, like in Go), but once saved as assembly source, it fails to run from this assembly source code, because a K value is expected to be on a single line.

Badly scoped vars at runtime

A variable with the same name as one in a parent scope doesn't get defined in its local scope, only when it doesn't exist anywhere else.

Easy fix: at compile-time, save a list of locals in the func prototype. At func instantiation, force-declare all locals before running. Removes the need for expected vars count.

[delete]

The missing language features.

Better upvalue management in closures

Right now closures are "dumb", each function value keeps a reference to its whole environment recursively up until the module function. This makes closures easy to implement, but it keeps alive all values, regardless of whether or not they are actually used in the closure.

For better memory management, analyze the required values and keep only what's required.

Review the `this` behaviour

Make it consistent, maybe store in the agoraFuncVal, so that it stays with the value when a method is used in for..range and recover built-in.

0.3?

Will you provide a 0.3 version of your language?

Make "" and 0 truthy

In Lua and Ruby, the only falsy values are nil and false. This makes it very convenient to check if a value is defined without worrying about what types the value may be. (It's usually easy to know if a value may be boolean.) If strings and numbers are allowed to be false, then I have to worry about how I will treat those special falsy values in every if statement. That's a lot of extra mental load, and it would be worse than if the interpreter to threw an error for non-boolean if expressions. Historically, when other languages allow "" and 0 to be false, it's because the language did not start out with a native boolean type, and they want backward compatibility. I hope you'll reconsider this.

stdlib tests fail on windows

1 TestFmtPrint gets func:%v... (no "!")

2 TestOsExec fails as echo is not a standalone program
Suggestion: make 'echo.bat' file containing '@echo %*'
Also, you would need to check for exp+"\r\n" too or ret.String()[:len(exp)] != exp instead
Note that if you had "hello world" windows would further complcate by placing " at each end

Otherwise it seems to work on win32 (GOOS=windows GOARCH=386)
Regards, Tony

Implement closures

Even required for simple cases like calling a func declared in the module, because the module itself is a function, so it needs to close over those funcs - see 46-json.agora.

Print nested objects is incoherent

The top-level object gets printed ok, since it is converted to its native (map) value, but the inner objects panic because runtime.object does not support conversion to String() and inner fields are not converted to native values.

Remove dumper interface from Val

Instead, make it a separate, public interface, and check if Val implements this interface at runtime to determine how to pretty-print the value (and fall back on %v or something to print by default - which would end up using the .String() implementation?).

y := x = x + 1 is accepted and does strange things.

fmt := import("fmt")

x := 0
fmt.Println(x) // A
y := x = x + 1
fmt.Println(x, y)

This program prints:

0
1 2

Comment out line A and it prints:

runtime error: index out of range

In my opinion, this code should not compile.

I ran these snippets using agora run -R

agora version: 8701d7f
Go version: go version devel +84975e4930dd Tue Sep 17 18:06:58 2013 -0700 linux/amd64

Default Val implementation

Provide a default implementation, so that values only need to "override" the operations hat are valid.

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.