Skip to the content.

fake

Codacy Badge

中文 English

Lightweight embeddable scripting language in C++. Syntax is borrowed from Lua, Go, and Erlang. Scripts are parsed with flex/bison, compiled to bytecode, and run on a VM.

Features

Requirements

Build

./build.sh           # debug
./build.sh release   # optimized

This produces bin/libfake.so, bin/fakebin, bin/fake_tests, and bin/fake_bench. The first configure downloads GoogleTest and Google Benchmark.

Usage

Run a script:

./bin/fakebin your.fk

Script tests are in test/scripts (lang, bind, stdlib, optimizer, template). Shared script libraries are in package/. After a build:

ctest --output-on-failure
./bin/fake_tests --gtest_filter=Language.*

CI (Linux/macOS × debug/release) runs GoogleTest and Google Benchmark on every push.

Embed in C++ — copy include/fake-inc.h and bin/libfake.so into your project:

fake *fk = newfake();
fkreg(fk, "cfunc1", cfunc1);
fkreg(fk, "memfunc1", &class1::memfunc1);  // same name on different classes does not clash
fkparse(fk, argv[1]);
int ret = fkrun<int>(fk, "myfunc1", 1, 2);  // runs to completion; does not leave a paused VM
fkparse(fk, argv[1]);  // parse or fkreg again — same name is replaced
fkreset(fk);  // drop runtime arrays/maps/pointers/strings; keep bytecode and C bindings
delfake(fk);  // destroy the instance and free everything

Lifetime

Call What it frees What it keeps
fkparse / fkreg again Previous bytecode or C binding of that name Everything else
fkreset(fk) Runtime arrays, maps, pointer wrappers, interned runtime strings, stacks Bytecode, constants, registered C functions
fkclear(fk) All compiled bytecode C bindings
delfake(fk) The whole instance

Call fkreset() only when no script is running. fkrun always finishes (or hangs) before it returns to the host. Do not replace a function that is currently on the call stack.

Language

package mypackage.test
include "common.fk"

struct teststruct
	sample_a
	sample_b
	sample_c
end

const hellostring = "hello"
const helloint = 1234
const hellomap = {1 : "a" 2 : "b" 3 : [1 2 3]}

func myfunc1(arg1, arg2)
	arg3 := cfunc1(helloint) + arg2:memfunc1(arg1)

	if arg1 < arg2 then
		fake myfunc2(arg1, arg2)
	elseif arg1 == arg2 then
		print("elseif")
	else
		print("else")
	end

	for var i = 0, i < arg2, i++ then
		print("i = ", i)
	end

	var a = array()
	a[1] = 3

	var b = map()
	b[a] = 1
	b[1] = a

	var uid = 1241515236123614u
	log("uid = ", uid)

	var ret1, var ret2 = myfunc2()
	ret1 = otherpackage.test.myfunc1(arg1, arg2)

	var tt = teststruct()
	tt->sample_a = 1
	tt->sample_b = teststruct()
	tt->sample_b->sample_a = 10

	switch arg1
		case 1 then
			print("1")
		case "a" then
			print("a")
		default
			print("default")
	end

	return arg1, arg3
end

Debugging

CLI (bin/fakebin):

debug

Benchmarks

See benchmark/README.md (中文).

./build.sh release
./bin/fake_bench --benchmark_min_time=0.5s

Release -O3 -flto only. CI’s 0.1s run is a smoke test, not the scoreboard. benchmark/*.lua are the same loop / prime / string workloads for a manual Lua comparison.

License

MIT

Stargazers over time

Stargazers over time