Skip to content

ozanh/ugo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

The uGO Language

Go Reference Go Report Card uGO Test uGO Dev Test Maintainability

uGO is a fast, dynamic scripting language to embed in Go applications. uGO is compiled and executed as bytecode on stack-based VM that's written in native Go.

uGO is actively used in production to evaluate Sigma Rules' conditions, and to perform compromise assessment dynamically.

To see how fast uGO is, please have a look at fibonacci benchmarks (not updated frequently).

Play with uGO via Playground built for WebAssembly.

Fibonacci Example

param arg0

var fib

fib = func(x) {
    if x == 0 {
        return 0
    } else if x == 1 {
        return 1
    }
    return fib(x-1) + fib(x-2)
}
return fib(arg0)

Features

  • Written in native Go (no cgo).
  • Supports Go 1.15 and above.
  • if else statements.
  • for and for in statements.
  • try catch finally statements.
  • param, global, var and const declarations.
  • Rich builtins.
  • Pure uGO and Go Module support.
  • Go like syntax with additions.
  • Call uGO functions from Go.
  • Import uGO modules from any source (file system, HTTP, etc.).
  • Create wrapper functions for Go functions using code generation.

Why uGO

uGO name comes from the initials of my daughter's, wife's and my name. It is not related with Go.

I needed a faster embedded scripting language with runtime error handling.

Quick Start

go get github.com/ozanh/ugo@latest

uGO has a REPL application to learn and test uGO scripts.

go install github.com/ozanh/ugo/cmd/ugo@latest

./ugo

repl-gif

This example is to show some features of uGO.

https://play.golang.org/p/1Tj6joRmLiX

package main

import (
    "fmt"

    "github.com/ozanh/ugo"
)

func main() {
    script := `
param ...args

mapEach := func(seq, fn) {

    if !isArray(seq) {
        return error("want array, got " + typeName(seq))
    }

    var out = []

    if sz := len(seq); sz > 0 {
        out = repeat([0], sz)
    } else {
        return out
    }

    try {
        for i, v in seq {
            out[i] = fn(v)
        }
    } catch err {
        println(err)
    } finally {
        return out, err
    }
}

global multiplier

v, err := mapEach(args, func(x) { return x*multiplier })
if err != undefined {
    return err
}
return v
`

    bytecode, err := ugo.Compile([]byte(script), ugo.DefaultCompilerOptions)
    if err != nil {
        panic(err)
    }
    globals := ugo.Map{"multiplier": ugo.Int(2)}
    ret, err := ugo.NewVM(bytecode).Run(
        globals,
        ugo.Int(1), ugo.Int(2), ugo.Int(3), ugo.Int(4),
    )
    if err != nil {
        panic(err)
    }
    fmt.Println(ret) // [2, 4, 6, 8]
}

Roadmap

Examples for best practices (2023).

Better Playground (2023).

More standard library modules (2023).

Configurable Stdin, Stdout and Stderr per Virtual Machine (2023).

Deferring function calls (2024).

Concurrency support (2024).

Documentation

LICENSE

uGO is licensed under the MIT License.

See LICENSE for the full license text.

Acknowledgements

uGO is inspired by script language Tengo by Daniel Kang. A special thanks to Tengo's creater and contributors.