_ _ ___ ___ ___ ___|_|___| |_ | . |_ -| _| _| | . | _| |_ |___|___|_| |_| _|_| |___| |_| 🎮Play | 📘Features | 🌰Demo | 🔧Install | 👾REPL | 🎉Syntax | 🎁Standard library | 💡Contact Author | 🇨🇳中文
This is a statically and strongly typed language written in Go, the syntax of Java and Go is referenced.
Provides the ability to write Go language in script form, retains the advantages of Go language (goroutine, etc.), and adds more syntactic sugar for ease of use.
The current Alpha version is for study and experimentation only.
hello_world.gs:
println("hello world");❯ gscript hello_world.gs hello worldOnline address: https://gscript.crossoverjie.top/
Source code:https://github.com/crossoverJie/gscript-homepage
- Class declaration
- Function declaration and call
- Primitive type:
int/string/float/bool/byte - Array type
niltypeanytype- Function type
- Closure:Functions as First-Class Objects
- Native function
- Standard library
- Variable arguments
- Operator overloading
- Native support
json - Native support
http - Example
- PKG manager
- Unit Test command line
println("hello world");funcint()fib(){inta=0;intb=1;intfibonacci(){intc=a;a=b;b=a+c;returnc;}returnfibonacci;}funcint()f=fib();for(inti=0;i<10;i++){println(f());}This is a dynamic web application written in GScript.
https://gscript.crossoverjie.top/api/index
Source code: https://github.com/crossoverjie/gscript-homepage
intnum(intx,inty){if(y==1||y==x){return1;}intv1=num(x-1,y-1);intv2=num(x-1,y);intc=v1+v2;// int c = num(x - 1, y - 1)+num(x - 1, y);returnc;}printTriangle(introw){for(inti=1;i<=row;i++){for(intj=1;j<=row-i;j++){print(" ");}for(intj=1;j<=i;j++){print(num(i,j)+" ");}println("");}}printTriangle(7);// output:111121133114641151010511615201561More examples:https://github.com/crossoverJie/gscript/tree/main/example
Download the latest binaries here
docker pull crossoverjie/gscriptdocker run --rm -it crossoverjie/gscript:latest gscriptdocker run --rm -v $PWD:/usr/src/gscript -w /usr/src/gscript crossoverjie/gscript gscript{yourpath}/temp.gsgit clone https://github.com/crossoverJie/gscript.git cd gscript make build-code ./gscript> ./gscript The current version supports four primitive type: int/string/float/bool and nil type.
Variable declaration syntax: type identifier (= expr)?.
inta=10;stringb,c;floate=10.1;boolf=false;byteby=1;stringx=^{"name": "bob","age": 20,"skill": {"lang": [{"go": {"feature": ["goroutine",true]}}]}}^Array declaration syntax: ('[' DECIMAL_LITERAL ']')? '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
// Declare and initializeint[]a={1,2,3};println(a);// Declare an empty array and specify the lengthint[] table =[4]{};println("");// Append data to array.append(a,4);println(a);for(inti=0;i<len(a);i++){println(a[i]);}// Access to data by index.intb=a[2];println(b);// byte arraystrings="10";byte[]a=toByteArray(s);printf("a=%v ",a);strings1=toString(a);printf("s1=%s",s1);assertEqual(s1,s);// slice an array into a new array.int[]a={1,2,3};ints=1;int[]b=a[s:len(a)];println(b);// output: [2 3]An any type may hold values of all type.
anya=10;println(a);intfun1(anya,intb){returna+b;}intv=fun1(1,2);println(v);assertEqual(v,3);anyv2=fun1(1,2);println(v2);assertEqual(v2,3);intfun2(inta,anyb){returna+b;}intv3=fun2(1,2);println(v3);assertEqual(v3,3);intfun3(anya,anyb){returna+b;}intv4=fun3(1,2);println(v4);assertEqual(v4,3);intfun4(anya,anyb){returna+b;}stringv5=fun4("10","20");println(v5);assertEqual(v5,"1020");Example: Standard library
classListNode{intvalue;ListNodenext;ListNode(intv,ListNoden){value=v;next=n;}}// The new keyword is not required to call the constructor.ListNodel1=ListNode(1,nil);// Using . to access object property or method.println(l1.value);The default comes with a parameterless constructor
classPerson{intage=10;stringname="abc";intgetAge(){return100+age;}}// parameterless constructorPersonxx=Person();println(xx.age);assertEqual(xx.age,10);println(xx.getAge());assertEqual(xx.getAge(),110);// cycle linked listboolhasCycle(ListNodehead){if(head==nil){returnfalse;}if(head.next==nil){returnfalse;}ListNodefast=head.next;ListNodeslow=head;boolret=false;for(fast.next!=nil){if(fast.next==nil){returnfalse;}if(fast.next.next==nil){returnfalse;}if(slow.next==nil){returnfalse;}if(fast==slow){ ret =true;returntrue;}fast=fast.next.next;slow=slow.next;}returnret;}ListNodel1=ListNode(1,nil);boolb1=hasCycle(l1);println(b1);assertEqual(b1,false);ListNodel4=ListNode(4,nil);ListNodel3=ListNode(3,l4);ListNodel2=ListNode(2,l3);boolb2=hasCycle(l2);println(b2);assertEqual(b2,false);l4.next=l2;boolb3=hasCycle(l2);println(b3);assertEqual(b3,true);Function declaration syntax: typeTypeOrVoid? IDENTIFIER formalParameters ('[' ']')*
add(inta){}When there is no return value, the return type can also be ignored.
Function type syntax: func typeTypeOrVoid '(' typeList? ')'
// External variable, global shared.intvarExternal=10;funcint(int)f1(){// Closure variable.intvarInner=20;intinnerFun(inta){println(a);intc=100;varExternal++;varInner++;returnvarInner;}returninnerFun;}// f2 is a function type, the return type and parameter are both int.funcint(int)f2=f1();for(inti=0;i<2;i++){println("varInner="+f2(i)+", varExternal="+varExternal);}println("=======");funcint(int)f3=f1();for(inti=0;i<2;i++){println("varInner="+f3(i)+", varExternal="+varExternal);}Output:
0 varInner=21, varExternal=11 1 varInner=22, varExternal=12 ======= 0 varInner=21, varExternal=13 1 varInner=22, varExternal=14 GScript also support variable arguments:
intadd(strings,int...num){println(s);intsum=0;for(inti=0;i<len(num);i++){intv=num[i];sum=sum+v;}returnsum;}intx=add("abc",1,2,3,4);println(x);assertEqual(x,10);Operator that Gscript support:
+-*/== != < <= > >=
Overloading function must be operator, and append operator.
classPerson{intage;Person(inta){age=a;}}Personoperator+(Personp1,Personp2){Personpp=Person(p1.age+p2.age);returnpp;}Personoperator-(Personp1,Personp2){Personpp=Person(p1.age-p2.age);returnpp;}Personoperator*(Personp1,Personp2){Personpp=Person(p1.age*p2.age);returnpp;}Personoperator/(Personp1,Personp2){Personpp=Person(p1.age/p2.age);returnpp;}booloperator==(Personp1,Personp2){returnp1.age==p2.age;}booloperator!=(Personp1,Personp2){returnp1.age!=p2.age;}booloperator>(Personp1,Personp2){returnp1.age>p2.age;}booloperator>=(Personp1,Personp2){returnp1.age>=p2.age;}booloperator<(Personp1,Personp2){returnp1.age<p2.age;}booloperator<=(Personp1,Personp2){returnp1.age<=p2.age;}Personp1=Person(10);Personp2=Person(20);//Person p3 = operator(p1,p2);Personp3=p1+p2;println("p3.age="+p3.age);assertEqual(p3.age,30);Personp4=p1-p2;println("p4.age="+p4.age);println(100-10);Personp5=p1*p2;println("p5.age="+p5.age);assertEqual(p5.age,200);Personp6=p2/p1;println("p6.age="+p6.age);assertEqual(p6.age,2);boolb1=p1==p2;println("b1=="+b1);assertEqual(b1,false);boolb2=p1!=p2;println("b2=="+b2);assertEqual(b2,true);boolb3=p1>p2;println("b3=="+b3);assertEqual(b3,false);boolb4=p1>=p2;println("b4=="+b4);assertEqual(b4,false);boolb5=p1<p2;println("b5=="+b5);assertEqual(b5,true);boolb6=p1<=p2;println("b6=="+b6);assertEqual(b6,true);More examples: https://github.com/crossoverJie/gscript/tree/main/example
Standard library source code: https://github.com/crossoverJie/gscript/tree/main/internal
printf("hello %s ","123");printf("hello-%s-%s ","123","abc");printf("hello-%s-%d ","123",123);strings=sprintf("nice to meet %s","you");println(s);assertEqual(s,"nice to meet you");int[]a={1,2,3};// len return array length.println(len(a));// Append data to array. append(a,4);println(a);// output: [1,2,3,4]// Assert function assertEqual(len(a),4);// Return hashcodeinthashcode=hash(key);// Serialize to JSON string.classP{stringname;P(stringn){name=n;}}classObject{Pp;intx;Object(Ppp,intxx){p=pp;x=xx;}}Pp1=P("abc");Objecto1=Object(p1,100);stringjson=JSON(o1);println(json);//{"p":{"name":"abc"},"x":100}// Query json with pathintx=JSONGet(json,"x");println(x);assertEqual(x,100);stringname=JSONGet(json,"p.name");println(name);assertEqual(name,"abc");// Get command-line arguments.Systems=System();string[]args=s.getOSArgs();Reference JSON query syntax: xjson
classMap{put(anykey,anyvalue){}anyget(anykey){}}intcount=100;Mapm1=Map();for(inti=0;i<count;i++){stringkey=i+"";stringvalue=key;m1.put(key,value);}println(m1.getSize());assertEqual(m1.getSize(),count);for(inti=0;i<count;i++){stringkey=i+"";stringvalue=m1.get(key);println("key="+key+":"+value);assertEqual(key,value);}classStringBuilder{byte[] buf = [0]{}; // append contents to buf, it returns the length of sintwriteString(strings){} // append b to buf, it returns the length of b.intWriteBytes(byte[] b){} // copies the buffer to a new.grow(intn){} stringString(){} }StringBuilderb = StringBuilder(); b.writeString("10"); b.writeString("20"); intl = b.writeString("30"); strings = 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);classStrings{// concatenates the elements of its first argument to create a single string. The separator// string sep is placed between elements in the resulting string.stringjoin(string[] elems, stringsep){} // tests whether the string s begins with prefix.boolhasPrefix(strings, stringprefix){} }Stringss = Strings(); string[] elems ={"name=xxx","age=xx"}; stringret = s.join(elems, "&"); println(ret); assertEqual(ret, "name=xxx&age=xx"); boolb = 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);Standard library:
// http lib// Response jsonFprintfJSON(intcode,stringpath,stringjson){}// Resonse htmlFprintfHTML(intcode,stringpath,stringhtml){}// path (relative paths may omit leading slash)stringQueryPath(stringpath){}stringFormValue(stringpath,stringkey){}classHttpContext{stringpath;JSON(intcode,anyv){stringjson=JSON(v);FprintfJSON(code,path,json);}HTML(intcode,anyv){stringhtml=v;FprintfHTML(code,path,html);}stringqueryPath(){stringp=QueryPath(path);returnp;}stringformValue(stringkey){stringv=FormValue(path,key);returnv;}}// Bind routehttpHandle(stringmethod,stringpath,func(HttpContext)handle){// println("path="+path);HttpContextctx=HttpContext();handle(ctx);}// Run http server.httpRun(stringaddr){}Start http service:
classPerson{stringname;}func(HttpContext)handle(HttpContextctx){Personp=Person();p.name="abc";println("p.name="+p.name);println("ctx="+ctx);ctx.JSON(200,p);}func(HttpContext)handle1(HttpContextctx){Personp=Person();p.name="def";println("p.name="+p.name);println("ctx="+ctx);ctx.JSON(200,p);}func(HttpContext)handle2(HttpContextctx){DateTimed=DateTime();stringlocal=d.getCurrentTime("Asia/Shanghai","2006-01-02 15:04:05");println(local);stringhtml=^<html><title>hello</title><h1>current ^+ local +^</h1><p>hahaha</p></html>^;stringqueryPath=ctx.queryPath();println("queryPath = "+queryPath);// http://127.0.0.1:8000/p/2?id=100stringid=ctx.formValue("id");println("id="+id);ctx.HTML(200,html);}httpHandle("get","/p",handle);httpHandle("get","/p/1",handle1);httpHandle("get","/p/2",handle2);httpRun(":8000");crossoverJie#gmail.com


