MCPcopy Index your code
hub / github.com/crossoverJie/gscript

github.com/crossoverJie/gscript @v0.0.12

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.0.12 ↗ · + Follow
1,896 symbols 4,071 edges 52 files 535 documented · 28%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README
 _     _   
 ___ ___ ___ ___|_|___| |_ 
| . |_ -|  _|  _| | . |  _|
|_  |___|___|_| |_|  _|_|  
|___|             |_|   

🎮Play | 📘特性 | 🌰例子 | 🔧安装 | 👾REPL | 🎉语法 | 🎁标准库 | 💡联系作者 | 🇦🇺英文文档

介绍

这是一门用 Go 编写的一款静态、强类型的脚本语言,大部分语法参考了 Java 以及少量的 Go

目标

提供类似于以脚本形式编写 Go 语言的能力,保留 Go 语言优点(goroutine等),新增更多易用性的语法糖。

当前为 Alpha 版本仅供学习与实验。

运行:

hello_world.gs:

println("hello world");
❯ gscript hello_world.gs
hello world

Playground

在线地址: https://gscript.crossoverjie.top/

源码地址: https://github.com/crossoverJie/gscript-homepage

特性

例子

Hello world

println("hello world");

打印斐波那契数列

func int() fib(){
    int a = 0;
    int b = 1;
    int fibonacci(){
        int c = a;
        a = b;
        b = a+c;
        return c;
    }
    return fibonacci;
}

func int() f = fib();

for (int i = 0; i < 10; i++){
    println(f());
}

网站应用

这是用 GScript 编写的动态网页:

https://gscript.crossoverjie.top/api/index

源码地址: https://github.com/crossoverjie/gscript-homepage

杨辉三角

int num(int x,int y){
    if (y==1 || y ==x) {
        return 1;
    }
    int v1 = num(x - 1, y - 1);
    int v2 = num(x - 1, y);
    int c = v1+v2;
    // int c = num(x - 1, y - 1)+num(x - 1, y);
    return c;
}

printTriangle(int row){
    for (int i = 1; i <= row; i++) {
        for (int j = 1; j <= row - i; j++) {
           print(" ");
        }
        for (int j = 1; j <= i; j++) {
            print(num(i, j) + " ");
        }
        println("");
    }
}

printTriangle(7);

// output:
      1 
     1 1 
    1 2 1 
   1 3 3 1 
  1 4 6 4 1 
 1 5 10 10 5 1 
1 6 15 20 15 6 1

更多例子:https://github.com/crossoverJie/gscript/tree/main/example

安装

二进制文件

在这里下载最新的二进制文件 here

🐳Docker

docker pull crossoverjie/gscript

REPL

docker run --rm -it  crossoverjie/gscript:latest gscript

运行脚本

docker run --rm -v $PWD:/usr/src/gscript -w /usr/src/gscript crossoverjie/gscript gscript {yourpath}/temp.gs

源码构建

git clone https://github.com/crossoverJie/gscript.git
cd gscript
make build-code
./gscript

REPL

> ./gscript 

语法

基本类型

当前版本支持 int/string/float/bool 四种基本类型以及 nil 特殊类型。

变量声明语法:type identifier (= expr)?

int a=10;
string b,c;
float e = 10.1;
bool f = false;
byte by = 1;
string x = ^
{
    "name": "bob",
    "age": 20,
    "skill": {
        "lang": [
            {
                "go": {
                    "feature": [
                        "goroutine",
                        true
                    ]
                }
            }
        ]
    }
}^;

数组

数组声明语法:('[' DECIMAL_LITERAL ']')? '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'

// 声明并初始化
int[] a={1,2,3};
println(a);

// 声明一个空数组并指定大小
int[] table = [4]{};

println("");
// 向数组 append 数据
a = append(a,4);
println(a);
for(int i=0;i<len(a);i++){
    println(a[i]);
}

// 通过下标获取数组数据
int b=a[2];
println(b);


// byte array
string s = "10";
byte[] a= toByteArray(s);
printf("a=%v ",a);
string s1 = toString(a);
printf("s1=%s",s1);
assertEqual(s1,s);

// 将数组切片为新的数组
// slice an array into a new array.
int[] a = {1,2,3};
int s=1;
int[] b = a[s:len(a)];
println(b);
// output: [2 3]

any

any 是通用类型,类似于 Java 中的 Object 和 Go 中的 interface{}

any a =10;
println(a);

int fun1(any a,int b){
    return a+b;
}
int v =fun1(1,2);
println(v);
assertEqual(v,3);

any v2 = fun1(1,2);
println(v2);
assertEqual(v2,3);

int fun2(int a, any b){
    return a+b;
}
int v3 =fun2(1,2);
println(v3);
assertEqual(v3,3);

int fun3(any a, any b){
    return a+b;
}
int v4 =fun3(1,2);
println(v4);
assertEqual(v4,3);

int fun4(any a, any b){
    return a+b;
}
string v5 =fun4("10", "20");
println(v5);
assertEqual(v5,"1020");

标准库中有相关应用。

Class

自定义 Class 与 Java 类似:

class ListNode{
    int value;
    ListNode next;
    ListNode(int v, ListNode n){
        value =v;
        next = n;
    }
}

// 调用构造函数时不需要使用 new 关键字。
ListNode l1 = ListNode(1, nil);

// 使用 . 调用对象属性或函数。
println(l1.value);

缺省情况下 class 具有无参构造函数:

class Person{
    int age=10;
    string name="abc";
    int getAge(){
        return 100+age;
    }
}

// 无参构造函数
Person xx= Person();
println(xx.age);
assertEqual(xx.age, 10);
println(xx.getAge());
assertEqual(xx.getAge(), 110);

函数

// 判断链表是否有环
bool hasCycle(ListNode head){
    if (head == nil){
        return false;
    }
    if (head.next == nil){
        return false;
    }

    ListNode fast = head.next;
    ListNode slow = head;
    bool ret = false;
    for (fast.next != nil){
        if (fast.next == nil){
            return false;
        }
        if (fast.next.next == nil){
            return false;
        }
        if (slow.next == nil){
            return false;
        }
        if (fast == slow){
            ret = true;
            return true;
        }

        fast = fast.next.next;
        slow = slow.next;
    }
    return ret;
}

ListNode l1 = ListNode(1, nil);
bool b1 =hasCycle(l1);
println(b1);
assertEqual(b1, false);

ListNode l4 = ListNode(4, nil);
ListNode l3 = ListNode(3, l4);
ListNode l2 = ListNode(2, l3);
bool b2 = hasCycle(l2);
println(b2);
assertEqual(b2, false);

l4.next = l2;
bool b3 = hasCycle(l2);
println(b3);
assertEqual(b3, true);

函数声明语法:typeTypeOrVoid? IDENTIFIER formalParameters ('[' ']')*

add(int a){}

当函数没有返回值时,可以声明为 void 或直接忽略返回类型。

闭包

GScript 中,函数作为一等公民可以作为变量传递,同时也能实现闭包。

函数类型语法:func typeTypeOrVoid '(' typeList? ')'

// 外部变量,全局共享。
int varExternal =10;
func int(int) f1(){
    // 闭包变量对每个闭包单独可见
    int varInner = 20;
    int innerFun(int a){
        println(a);
        int c=100;
        varExternal++;
        varInner++;
        return varInner;
    }
    return innerFun;
}

// f2 作为一个函数类型,接收的是一个返回值和参数都是 int 的函数。
func int(int) f2 = f1();
for(int i=0;i<2;i++){
    println("varInner=" + f2(i) + ", varExternal=" + varExternal);
}
println("=======");
func int(int) f3 = f1();
for(int i=0;i<2;i++){
    println("varInner=" + f3(i) + ", varExternal=" + varExternal);
}

最终输出如下:

0
varInner=21, varExternal=11
1
varInner=22, varExternal=12
=======
0
varInner=21, varExternal=13
1
varInner=22, varExternal=14

可变参数

GScript 支持函数定义可变参数,语法如下:

int add(string s, int ...num){
    println(s);
    int sum = 0;
    for(int i=0;i<len(num);i++){
        int v = num[i];
        sum = sum+v;
    }
    return sum;
}
int x = add("abc", 1,2,3,4);
println(x);
assertEqual(x, 10);

运算符重载

GScript 支持以下运算符重载: - +-*/ - == != < <= > >=

重载函数名称必须是 operator,名称后跟上运算符即可重载。

class Person{
    int age;
    Person(int a){
        age = a;
    }
}
Person operator + (Person p1, Person p2){
    Person pp = Person(p1.age+p2.age);
    return pp;
}
Person operator - (Person p1, Person p2){
    Person pp = Person(p1.age-p2.age);
    return pp;
}
Person operator * (Person p1, Person p2){
    Person pp = Person(p1.age * p2.age);
    return pp;
}
Person operator / (Person p1, Person p2){
    Person pp = Person(p1.age / p2.age);
    return pp;
}
bool operator == (Person p1, Person p2){
    return p1.age==p2.age;
}
bool operator != (Person p1, Person p2){
    return p1.age!=p2.age;
}
bool operator > (Person p1, Person p2){
    return p1.age>p2.age;
}
bool operator >= (Person p1, Person p2){
    return p1.age>=p2.age;
}
bool operator < (Person p1, Person p2){
    return p1.age<p2.age;
}
bool operator <= (Person p1, Person p2){
    return p1.age<=p2.age;
}
Person p1 = Person(10);
Person p2 = Person(20);
//Person p3 =  operator(p1,p2);
Person p3 = p1+p2;
println("p3.age="+p3.age);
assertEqual(p3.age, 30);

Person p4 = p1-p2;
println("p4.age="+p4.age);
println(100-10);

Person p5 = p1*p2;
println("p5.age="+p5.age);
assertEqual(p5.age, 200);

Person p6 = p2/p1;
println("p6.age="+p6.age);
assertEqual(p6.age, 2);

bool b1 = p1 == p2;
println("b1=="+b1);
assertEqual(b1,false);

bool b2 = p1 != p2;
println("b2=="+b2);
assertEqual(b2,true);

bool b3 = p1 > p2;
println("b3=="+b3);
assertEqual(b3,false);

bool b4 = p1 >= p2;
println("b4=="+b4);
assertEqual(b4,false);

bool b5 = p1 < p2;
println("b5=="+b5);
assertEqual(b5,true);

bool b6 = p1 <= p2;
println("b6=="+b6);
assertEqual(b6,true);

更多样例请参考:https://github.com/crossoverJie/gscript/tree/main/example

标准库

标准库源码:https://github.com/crossoverJie/gscript/tree/main/internal

内置函数


printf("hello %s ","123");
printf("hello-%s-%s ","123","abc");
printf("hello-%s-%d ","123",123);

string s = sprintf("nice to meet %s", "you");
println(s);
assertEqual(s,"nice to meet you");

int[] a={1,2,3};
// len 返回数组大小
println(len(a));

// 向数组追加数据
append(a,4);
println(a);
// output: [1,2,3,4]

// 断言函数,不相等时会抛出运行时异常,并中断程序。
assertEqual(len(a),4);

// 返回 hashcode
int hashcode = hash(key);

// 序列化 JSON 字符串
class P{
    string name;
    P(string n){
        name = n;
    }
}
class Object{
    P p;
    int x;
    Object(P pp, int xx){
        p = pp;
        x = xx;
    }
}
P p1 = P("abc");
Object o1 = Object(p1, 100);
string json = JSON(o1);
println(json); //{"p":{"name":"abc"},"x":100}

// 查询 JSON
int x = JSONGet(json,"x");
println(x);
assertEqual(x,100);

string name = JSONGet(json,"p.name");
println(name);
assertEqual(name,"abc");

// 获取启动参数
System s = System();
string[] args = s.getOSArgs();

更多 JSON 查询语法请参考:xjson

Map

函数定义

class Map{
    put(any key, any value){}
    any get(any key){}
}

用法

int count =100;
Map m1 = Map();
for (int i=0;i<count;i++){
    string key = i+"";
    string value = key;
    m1.put(key,value);
}
println(m1.getSize());
assertEqual(m1.getSize(),count);

for (int i=0;i<count;i++){
    string key = i+"";
    string value = m1.get(key);
    println("key="+key+ ":"+ value);
    assertEqual(key,value);
}

StringBuilder

函数定义

class StringBuilder{
    byte[] buf = [0]{};

    // append contents to buf, it returns the length of s
    int writeString(string s){}

    // append b to buf, it returns the length of b.
    int WriteBytes(byte[] b){}

    // copies the buffer to a new.
    grow(int n){}

    string String(){}
}

用法

StringBuilder b = StringBuilder();
b.writeString("10");
b.writeString("20");
int l = b.writeString("30");
string s = b.String();
printf("s:%s, len=%d ",s,l);
assertEqual(s,"102030");
byte[] b2 = toByteArray("40");
b.WriteBytes(b2);
s = b.String();
assertEqual(s,"10203040");
println(s);

Strings

函数定义

class Strings{
    // concatenates the elements of its first argument to create a single string. The separator
    // string sep is placed between elements in the resulting string.
    string join(string[] elems, string sep){}

    // tests whether the string s begins with prefix.
    bool hasPrefix(string s, string prefix){}
}

用法

Strings s = Strings();
string[] elems = {"name=xxx","age=xx"};
string ret = s.join(elems, "&");
println(ret);
assertEqual(ret, "name=xxx&age=xx");

bool b = s.hasPrefix("http://www.xx.com", "http");
println(b);
assertEqual(b,true);
b = s.hasPrefix("http://www.xx.com", "https");
println(b);
assertEqual(b,false);

http

标准库定义:

// http lib
// Response json
FprintfJSON(int code, string path, string json){}
// Resonse html
FprintfHTML(int code, string path, string html){}

// path (relative paths may omit leading slash)
string QueryPath(string path){}

string FormValue(string path, string key){}
class HttpContext{
    string path;
    JSON(int code, any v){
        string json = JSON(v);
        FprintfJSON(code, path, json);
    }
    HTML(int code, any v) {
        string html = v;
        FprintfHTML(code, path, html);
    }
    string queryPath() {
        string p = QueryPath(path);
        return p;
    }

    string formValue(string key){
        string v = FormValue(path, key);
        return v;
    }
}
// Bind route
httpHandle(string method, string path, func (HttpContext) handle){
    // println("path="+path);
    HttpContext ctx = HttpContext();
    handle(ctx);
}
// Run http server.
httpRun(string addr){}

启动一个 HTTP 服务:

```js class Person{ string name; } func (HttpContext) handle (HttpContext ctx){ Person p = Person(); p.name = "abc"; println("p.name=" + p.name); println("ctx=" + ctx); ctx.JSON(200, p); }

func (HttpContext) handle1 (HttpContext ctx){ Person p = Person(); p.name = "def"; println("p.name=" + p.name); println("ctx=" + ctx); ctx.JSON(200, p); } func (HttpContext) handle2 (HttpContext ctx){ DateTime d = DateTime(); string local = d.getCurrentTime("Asia/Shanghai","2006-01-02 15:04:05"); println(local); string html =^ hello

current ^+ local +^

hahaha

</html>
^;

Extension points exported contracts — how you extend this code

Object (Interface)
Object 变量对象,可以获取和保存变量的值 [2 implementers]
stack/stack.go
Type (Interface)
(no doc) [4 implementers]
symbol/symbol.go
GScriptListener (Interface)
GScriptListener is a complete listener for a parse tree produced by GScriptParser. [1 implementers]
parser/gscript_listener.go
IClassDeclarationContext (Interface)
IClassDeclarationContext is an interface to support dynamic dispatch. [1 implementers]
parser/gscript_parser.go
GScriptVisitor (Interface)
A complete Visitor for a parse tree produced by GScriptParser. [1 implementers]
parser/gscript_visitor.go
I (Interface)
(no doc) [1 implementers]
byte_test.go
FuncType (Interface)
function [2 implementers]
symbol/symbol.go
IClassBodyContext (Interface)
IClassBodyContext is an interface to support dynamic dispatch. [1 implementers]
parser/gscript_parser.go

Core symbols most depended-on inside this repo

NewCompiler
called by 161
compiler.go
Compiler
called by 154
compiler.go
GetName
called by 86
symbol/symbol.go
GetTokenType
called by 48
symbol/operator_overload.go
RuntimePanic
called by 45
log/log.go
GetValue
called by 45
stack/stack.go
IsType
called by 45
symbol/symbol.go
EnterRule
called by 42
parser/gscript_parser.go

Shape

Method 1,334
Function 410
Struct 96
Interface 51
TypeAlias 4
FuncType 1

Languages

Go100%

Modules by API surface

parser/gscript_parser.go924 symbols
parser/gscript_base_listener.go111 symbols
parser/gscript_listener.go107 symbols
symbol/symbol.go89 symbols
parser/gscript_visitor.go54 symbols
parser/gscript_base_visitor.go54 symbols
visitor.go51 symbols
stack/stack.go38 symbols
resolver/annotated_tree.go33 symbols
internal_function.go31 symbols
compile_log_test.go29 symbols
compiler_test.go28 symbols

For agents

$ claude mcp add gscript \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact