dune

package module
v0.0.0-...-6c5b1ce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2022 License: BSD-2-Clause Imports: 17 Imported by: 0

README

Dune

Dune is a virtual machine written in Go that executes a subset of Typescript.

It combines the simplicity, reliability and efficiency of Go with the flexibility of Typescript.

Download the latest release or install it from source:

go install github.com/scorredoira/dune/cmd/dune@latest

Examples

Create a hello.ts:

fmt.println("Hello world")

Run it:

$ dune hello.ts 
Hello world

REPL:

$ dune

Dune v1.0
commands: :paste, :help, :list, :asm, :quit

> 1 + 2
3

Arrays have multiple built in functions:

let items = [1, 2, 3, 4, 5]
let r = items.where(t => t > 2).select(t => t * t).sum()
console.log(r)

A web server:

let s = http.newServer()
s.address = ":8080"
s.handler = (w, r) => w.write("Hello world")
s.start() 

Working with databases:

let db = sql.open("sqlite3", ":memory:")
db.exec("CREATE TABLE people (id KEY, name TEXT)")
db.exec("INSERT INTO people (name) VALUES (?)", "Bob")
for (let r of db.query("SELECT id, name FROM people")) {
	console.log(r.id, r.name)
}

Permissions

By default a virtual machine has no access to the external world. The file system is virtual.

This code throws: unauthorized

let p = bytecode.compileStr(`http.get("http://google.com")`)
let vm = runtime.newVM(p)
vm.run()

Programs can request permissions with directives:

// [permissions networking]
http.get("http://google.com") 

Execution limits:

This code throws: Step limit reached: 100

let p = bytecode.compileStr(`while(true) { }`)
let vm = runtime.newVM(p)
vm.maxSteps = 100
vm.run()

This code throws: Max stack frames reached: 5

let p = bytecode.compileStr(`function main() { main() }`)
let vm = runtime.newVM(p)
vm.maxFrames = 5
vm.run()

MaxAllocations counts the number of variables set and in the case of strings their size so it is not very useful yet. This code throws: Max allocations reached: 10

let p = bytecode.compileStr(`
	let v = "*"
	while(true) {
		v += v
	}
`)
let vm = runtime.newVM(p)
vm.maxAllocations = 10
vm.run()

Checkout more examples.

Testing

Since everything is virtual, including the file system, programs are easily testable. There is an assert package in the standard library.

Writing programs

The syntax is a subset of Typescript to get type checking, autocompletion and refactoring tools from editors like VS Code.

$ dune --init
$ code rand.ts

Write a basic program:

export function main(len?: string) {
    let n = convert.toInt(len || "15")
    let v = crypto.randomAlphanumeric(n)
    fmt.println(v)
}   
$ dune rand
1RyXuMFKwmxPbTa6bpXk

Embedding

package main

import (
	"fmt"

	"github.com/scorredoira/dune"
)

func main() {
	v, err := dune.RunStr("return 3 * 2")
	fmt.Println(v, err)
}

To call Go functions:

package main

import (
	"fmt"
	"log"

	"github.com/scorredoira/dune"
)

func main() {
	dune.AddNativeFunc(dune.NativeFunction{
		Name:      "math.square",
		Arguments: 1,
		Function: func(this dune.Value, args []dune.Value, vm *dune.VM) (dune.Value, error) {
			v := args[0].ToInt()
			return dune.NewInt64(v * v), nil
		},
	})

	p, err := dune.CompileStr("return math.square(5)")
	if err != nil {
		log.Fatal(err)
	}

	v, err := dune.NewVM(p).Run()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(v)
}

To import the standard library:

package main

import (
	"log"

	"github.com/scorredoira/dune"
	_ "github.com/scorredoira/dune/lib"
)

func main() {
	_, err := dune.RunStr(`
		let v = { foo: 33 }
		console.log(v)
	`)

	if err != nil {
		log.Fatal(err)
	}
}

To decompile a program:

$ dune -d /tmp/rand.ts 

=============================
Functions
=============================

0F @global
-----------------------------
  0     return              --     --     --   ;   @global


1F main
-----------------------------
  0     MoveAndTest         2L     0L     3L   ;   /tmp/rand.ts:8
  1     TestJump            3L     1D     0D   ;   /tmp/rand.ts:8
  2     Move                2L     0K     --   ;   /tmp/rand.ts:8
  3     CallSingleArg      81N     1L     2L   ;   /tmp/rand.ts:8
  4     CallSingleArg     107N     4L     1L   ;   /tmp/rand.ts:9
  5     CallSingleArg     131N     --     4L   ;   /tmp/rand.ts:10
  6     Return              --     --     --   ;   /tmp/rand.ts:10

  0L len 0-6
  1L n 0-6
  2L @ 0-6
  3L @ 0-6
  4L v 4-6

=============================
Constants
=============================
0K string 15

Documentation

Index

Constants

View Source
const GlobalNamespace = "--globalnamespace"
View Source
const MAX_EXPORT_RECURSION = 200
View Source
const VERSION = "1.0"

Variables

View Source
var (
	UndefinedValue = Value{Type: Undefined}
	NullValue      = Value{Type: Null}
	TrueValue      = Value{Type: Bool, /* contains filtered or unexported fields */}
	FalseValue     = Value{Type: Bool, /* contains filtered or unexported fields */}
)
View Source
var ErrFunctionNotExist = errors.New("function not found")

Functions

func AddBuiltinField

func AddBuiltinField(name string)

func AddBuiltinFunc

func AddBuiltinFunc(name string)

func AddNativeFunc

func AddNativeFunc(f NativeFunction)

func Eval

func Eval(vm *VM, code string) error

func Fprint

func Fprint(w io.Writer, p *Program)

func FprintConstants

func FprintConstants(w io.Writer, p *Program)

func FprintFunction

func FprintFunction(w io.Writer, prefix string, f *Function, p *Program)

func FprintNames

func FprintNames(w io.Writer, p *Program, registers bool)

func NewCompiler

func NewCompiler() *compiler

func Parse

func Parse(fs filesystem.FS, path string) (*ast.Program, error)

func ParseExpr

func ParseExpr(code string) (ast.Expr, error)

func ParseStr

func ParseStr(code string) (*ast.Program, error)

func Print

func Print(p *Program)

func PrintFunction

func PrintFunction(f *Function, p *Program)

func PrintNames

func PrintNames(p *Program, registers bool)

func RegisterLib

func RegisterLib(funcs []NativeFunction, dts string)

func Sprint

func Sprint(p *Program) (string, error)

func SprintNames

func SprintNames(p *Program, registers bool) (string, error)

func Stacktrace

func Stacktrace() string

func TypeDefs

func TypeDefs() string

func Wrap

func Wrap(msg string, err error) error

Types

type Address

type Address struct {
	Kind  AddressKind
	Value int32
}

func NewAddress

func NewAddress(kind AddressKind, value int) *Address

func (*Address) Copy

func (a *Address) Copy() *Address

func (*Address) Equal

func (r *Address) Equal(b *Address) bool

func (*Address) String

func (r *Address) String() string

type AddressKind

type AddressKind byte
const (
	AddrVoid AddressKind = iota
	AddrLocal
	AddrGlobal
	AddrConstant
	AddrClosure
	AddrEnum
	AddrFunc
	AddrNativeFunc
	AddrClass
	AddrData
	AddrUnresolved
)

func (AddressKind) String

func (i AddressKind) String() string

type Allocator

type Allocator interface {
	Size() int
}

type Callable

type Callable interface {
	GetMethod(name string) NativeMethod
}

type Class

type Class struct {
	Name       string
	Module     string
	Attributes []string
	Fields     []*Field
	Getters    []int
	Setters    []int
	Functions  []int
	Exported   bool
}

func (*Class) Copy

func (c *Class) Copy() *Class

type Closure

type Closure struct {
	FuncIndex int
	// contains filtered or unexported fields
}

func (*Closure) Export

func (c *Closure) Export(recursionLevel int) interface{}

func (*Closure) Type

func (c *Closure) Type() string

type Comparable

type Comparable interface {
	Compare(Value) int
}

Comparable returns:

-2 if both values are imcompatible for comparisson between each other.
-1 is lesser
 0 is equal
 1 is greater

type CompilerError

type CompilerError struct {
	Pos ast.Position
	// contains filtered or unexported fields
}

func (CompilerError) Error

func (e CompilerError) Error() string

func (CompilerError) ErrorMessage

func (e CompilerError) ErrorMessage() string

func (CompilerError) Position

func (e CompilerError) Position() ast.Position

type EnumList

type EnumList struct {
	Name     string
	Module   string
	Values   []*EnumValue
	Exported bool
}

func (*EnumList) ValueByName

func (e *EnumList) ValueByName(name string) (*EnumValue, int)

type EnumValue

type EnumValue struct {
	Name   string
	KIndex int
}

type Enumerable

type Enumerable interface {
	Values() ([]Value, error)
}

type Equatable

type Equatable interface {
	Equals(interface{}) bool
}

type ErrorMessenger

type ErrorMessenger interface {
	ErrorMessage() string
}

type Exporter

type Exporter interface {
	Export(recursionLevel int) interface{}
}

type Field

type Field struct {
	Name     string
	Exported bool
}

type FieldGetter

type FieldGetter interface {
	GetField(string, *VM) (Value, error)
}

type FieldSetter

type FieldSetter interface {
	SetField(string, Value, *VM) error
}

type Finalizable

type Finalizable interface {
	Close() error
}

type Frame

type Frame uintptr

Frame represents a program counter inside a stack frame.

type Function

type Function struct {
	Name         string
	Module       string
	Attributes   []string
	Positions    []Position
	Instructions []*Instruction
	Closures     []*Register
	Registers    []*Register

	Arguments         int
	OptionalArguments int
	Index             int
	WrapClass         int
	MaxRegIndex       int
	Class             int
	Lambda            bool
	IsGlobal          bool
	IsClass           bool
	Exported          bool
	Variadic          bool
	Kind              FunctionKind
	// contains filtered or unexported fields
}

func (*Function) Copy

func (c *Function) Copy() *Function

func (*Function) HasPermission

func (f *Function) HasPermission(name string) bool

func (*Function) Permissions

func (f *Function) Permissions() []string

type FunctionKind

type FunctionKind byte
const (
	User FunctionKind = iota
	Init
	Main
	Global
)

type IndexIterator

type IndexIterator interface {
	IndexerGetter
	Len() int
}

type IndexerGetter

type IndexerGetter interface {
	GetIndex(int) (Value, error)
}

type IndexerSetter

type IndexerSetter interface {
	SetIndex(int, Value) error
}

type Instance

type Instance struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

func NewInstance

func NewInstance(name string, args []Value, vm *VM) (*Instance, error)

func (*Instance) Function

func (i *Instance) Function(name string, p *Program) (*Function, bool)

func (*Instance) GetField

func (i *Instance) GetField(name string, vm *VM) (Value, error)

func (*Instance) PropertyGetter

func (i *Instance) PropertyGetter(name string, p *Program) (*Function, bool)

func (*Instance) PropertySetter

func (i *Instance) PropertySetter(name string, p *Program) (*Function, bool)

func (*Instance) SetField

func (i *Instance) SetField(name string, v Value, vm *VM) error

func (*Instance) String

func (i *Instance) String() string

type Instruction

type Instruction struct {
	A      *Address
	B      *Address
	C      *Address
	Opcode Opcode
}

func NewInstruction

func NewInstruction(op Opcode, a, b, c *Address) *Instruction

func (*Instruction) Copy

func (r *Instruction) Copy() *Instruction

func (*Instruction) Format

func (i *Instruction) Format(padd bool) string

func (*Instruction) String

func (i *Instruction) String() string

type KeyGetter

type KeyGetter interface {
	GetKey(string) (Value, error)
}

type KeyIterator

type KeyIterator interface {
	KeyGetter
	Keys() []string
}

type Localizer

type Localizer interface {
	Format(language, format string, v interface{}) string
	ParseNumber(v string) (float64, error)
	ParseDate(value, format string, loc *time.Location) (time.Time, error)
}

type MapValue

type MapValue struct {
	Map map[Value]Value
	sync.RWMutex
}

type Method

type Method struct {
	ThisObject Value
	FuncIndex  int
}

func (*Method) Export

func (*Method) Export(recursionLevel int) interface{}

func (*Method) Type

func (*Method) Type() string

type NamedType

type NamedType interface {
	Type() string
}

type NativeFunction

type NativeFunction struct {
	Function    func(this Value, args []Value, vm *VM) (Value, error)
	Name        string
	Permissions []string
	Arguments   int
	Index       int
}

NativeFunction is a function written in Go as opposed to an interpreted function

func AllNativeFuncs

func AllNativeFuncs() []NativeFunction

func NativeFuncFromIndex

func NativeFuncFromIndex(i int) NativeFunction

func NativeFuncFromName

func NativeFuncFromName(name string) (NativeFunction, bool)

type NativeMethod

type NativeMethod func(args []Value, vm *VM) (Value, error)

func (NativeMethod) Type

func (NativeMethod) Type() string

type NativeObject

type NativeObject interface {
	GetMethod(name string) NativeMethod
	GetField(name string, vm *VM) (Value, error)
	SetField(name string, v Value, vm *VM) error
}

type NewArrayObject

type NewArrayObject struct {
	Array []Value
}

type Opcode

type Opcode byte

func (Opcode) String

func (i Opcode) String() string

type Position

type Position struct {
	File   int
	Line   int
	Column int
}

func (Position) Copy

func (p Position) Copy() Position

type Program

type Program struct {
	Resources map[string][]byte

	Attributes []string
	Enums      []*EnumList
	Classes    []*Class
	Files      []string

	Functions []*Function
	Constants []Value
	Name      string

	sync.Mutex
	// contains filtered or unexported fields
}

func Compile

func Compile(fs filesystem.FS, path string) (*Program, error)

func CompileStr

func CompileStr(code string) (*Program, error)

func (*Program) AddPermission

func (p *Program) AddPermission(name string)

func (*Program) Attribute

func (p *Program) Attribute(name string) string

func (*Program) Copy

func (p *Program) Copy() *Program

func (*Program) FileIndex

func (p *Program) FileIndex(file string) int

func (*Program) Function

func (p *Program) Function(name string) (*Function, bool)

func (*Program) HasPermission

func (p *Program) HasPermission(name string) bool

func (*Program) Permissions

func (p *Program) Permissions() []string

func (*Program) SetAttribute

func (p *Program) SetAttribute(key, value string)

func (*Program) Strip

func (p *Program) Strip()

func (*Program) ToTraceLine

func (p *Program) ToTraceLine(f *Function, pc int) TraceLine

type Register

type Register struct {
	KAddress *Address
	Module   string
	Name     string
	Index    int
	StartPC  int
	EndPC    int
	Exported bool
}

func (*Register) Copy

func (r *Register) Copy() *Register

func (*Register) Equals

func (r *Register) Equals(b *Register) bool

type StackTrace

type StackTrace []Frame

StackTrace is stack of Frames from innermost (newest) to outermost (oldest).

type TraceLine

type TraceLine struct {
	Function string
	File     string
	Line     int
}

func (TraceLine) SameLine

func (p TraceLine) SameLine(o TraceLine) bool

func (TraceLine) String

func (p TraceLine) String() string

type Type

type Type int8
const (
	Null Type = iota
	Undefined
	Int
	Float
	Bool
	Bytes
	String
	Array
	Map
	Func
	Enum
	NativeFunc
	Rune
	Object
)

func (Type) String

func (t Type) String() string

type VM

type VM struct {
	Context    Value
	StdLib     Value
	Now        time.Time
	RetValue   Value
	Localizer  Localizer
	Stderr     io.Writer
	Error      error
	FileSystem filesystem.FS
	Stdout     io.Writer
	Stdin      io.Reader

	Location *time.Location

	Program  *Program
	Language string

	MaxFrames      int
	MaxAllocations int64
	MaxSteps       int64
	// contains filtered or unexported fields
}

func NewInitializedVM

func NewInitializedVM(p *Program, globals []Value) *VM

func NewVM

func NewVM(p *Program) *VM

func (*VM) AddAllocations

func (vm *VM) AddAllocations(size int) error

func (*VM) AddSteps

func (vm *VM) AddSteps(n int64) error

func (*VM) Allocations

func (vm *VM) Allocations() int64

func (*VM) Clone

func (vm *VM) Clone(p *Program) *VM

func (*VM) CloneInitialized

func (vm *VM) CloneInitialized(p *Program, globals []Value) *VM

func (*VM) CurrentFunc

func (vm *VM) CurrentFunc() *Function

func (*VM) FinalizeGlobals

func (vm *VM) FinalizeGlobals()

func (*VM) GetStderr

func (vm *VM) GetStderr() io.Writer

func (*VM) GetStdin

func (vm *VM) GetStdin() io.Reader

func (*VM) GetStdout

func (vm *VM) GetStdout() io.Writer

func (*VM) Globals

func (vm *VM) Globals() []Value

func (*VM) HasPermission

func (vm *VM) HasPermission(name string) bool

func (*VM) Initialize

func (vm *VM) Initialize() error

func (*VM) Initialized

func (vm *VM) Initialized() bool

func (*VM) NewCodeError

func (vm *VM) NewCodeError(code int, format string, a ...interface{}) *VMError

func (*VM) NewError

func (vm *VM) NewError(format string, a ...interface{}) *VMError

func (*VM) RegisterValue

func (vm *VM) RegisterValue(name string) (Value, bool)

return a value from the current scope

func (*VM) ResetSteps

func (vm *VM) ResetSteps()

func (*VM) Run

func (vm *VM) Run(args ...Value) (Value, error)

func (*VM) RunClosure

func (vm *VM) RunClosure(c *Closure, args ...Value) (Value, error)

RunClosure executes a program closure

func (*VM) RunFunc

func (vm *VM) RunFunc(name string, args ...Value) (Value, error)

RunFunc executes a function by name

func (*VM) RunFuncIndex

func (vm *VM) RunFuncIndex(index int, args ...Value) (Value, error)

RunFuncIndex executes a program function by index

func (*VM) RunMethod

func (vm *VM) RunMethod(c *Method, args ...Value) (Value, error)

RunMethod executes a class method

func (*VM) SetFinalizer

func (vm *VM) SetFinalizer(v Finalizable)

func (*VM) SetGlobalFinalizer

func (vm *VM) SetGlobalFinalizer(v Finalizable)

func (*VM) SetGlobalRegister

func (vm *VM) SetGlobalRegister(name string, v Value) error

func (*VM) Stacktrace

func (vm *VM) Stacktrace() []string

func (*VM) StacktraceLine

func (vm *VM) StacktraceLine() string

func (*VM) Steps

func (vm *VM) Steps() int64

func (*VM) WrapError

func (vm *VM) WrapError(err error) *VMError

type VMError

type VMError struct {
	Wrapped    *VMError
	Message    string
	Details    string
	Code       int
	IsRethrow  bool
	TraceLines []TraceLine
	// contains filtered or unexported fields
}

func NewCodeError

func NewCodeError(code int, msg string, args ...interface{}) *VMError

func (*VMError) Error

func (e *VMError) Error() string

func (*VMError) ErrorMessage

func (e *VMError) ErrorMessage() string

func (*VMError) GetField

func (e *VMError) GetField(name string, vm *VM) (Value, error)

func (*VMError) GetMethod

func (e *VMError) GetMethod(name string) NativeMethod

func (*VMError) Is

func (e *VMError) Is(msg string) bool

func (*VMError) MarshalJSON

func (e *VMError) MarshalJSON() ([]byte, error)

func (*VMError) SetField

func (e *VMError) SetField(key string, v Value, vm *VM) error

func (*VMError) Stack

func (e *VMError) Stack() string

func (*VMError) String

func (e *VMError) String() string

func (*VMError) Type

func (e *VMError) Type() string

type Value

type Value struct {
	Type Type
	// contains filtered or unexported fields
}

func NewArray

func NewArray(size int) Value

func NewArrayValues

func NewArrayValues(v []Value) Value

func NewBool

func NewBool(v bool) Value

func NewBytes

func NewBytes(v []byte) Value

func NewEnum

func NewEnum(v int) Value

func NewFloat

func NewFloat(v float64) Value

func NewFunction

func NewFunction(v int) Value

func NewInt

func NewInt(v int) Value

func NewInt64

func NewInt64(v int64) Value

func NewMap

func NewMap(size int) Value

func NewMapValues

func NewMapValues(m map[Value]Value) Value

func NewNativeFunction

func NewNativeFunction(v int) Value

func NewObject

func NewObject(v interface{}) Value

func NewRune

func NewRune(v rune) Value

func NewString

func NewString(v string) Value

func NewValue

func NewValue(v interface{}) Value

func Run

func Run(fs filesystem.FS, path string) (Value, error)

func RunStr

func RunStr(code string) (Value, error)

func (Value) Equals

func (v Value) Equals(other Value) bool

func (Value) Export

func (v Value) Export(recursionLevel int) interface{}

func (Value) ExportMarshal

func (v Value) ExportMarshal(recursionLevel int) interface{}

func (Value) IsNil

func (v Value) IsNil() bool

func (Value) IsNilOrEmpty

func (v Value) IsNilOrEmpty() bool

func (Value) MarshalJSON

func (v Value) MarshalJSON() ([]byte, error)

func (Value) Size

func (v Value) Size() int

func (Value) StrictEquals

func (v Value) StrictEquals(other Value) bool

func (Value) String

func (v Value) String() string

String representation for the formatter.

func (Value) ToArray

func (v Value) ToArray() []Value

func (Value) ToArrayObject

func (v Value) ToArrayObject() *NewArrayObject

func (Value) ToBool

func (v Value) ToBool() bool

func (Value) ToBytes

func (v Value) ToBytes() []byte

func (Value) ToEnum

func (v Value) ToEnum() int

func (Value) ToFloat

func (v Value) ToFloat() float64

func (Value) ToFunction

func (v Value) ToFunction() int

func (Value) ToInt

func (v Value) ToInt() int64

func (Value) ToMap

func (v Value) ToMap() *MapValue

func (Value) ToNativeFunction

func (v Value) ToNativeFunction() int

func (Value) ToObject

func (v Value) ToObject() interface{}

func (Value) ToObjectOrNil

func (v Value) ToObjectOrNil() interface{}

func (Value) ToRune

func (v Value) ToRune() rune

func (Value) ToString

func (v Value) ToString() string

func (Value) TypeName

func (v Value) TypeName() string

Directories

Path Synopsis
cmd
lib
dbx
sqx
templates
Package templates generates source code for templates.
Package templates generates source code for templates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL