Skip to content

💪🏻This is a statically and strongly typed language written in Go.|GScript 是用 Go 编写的静态、强类型的脚本语言。

License

Notifications You must be signed in to change notification settings

crossoverJie/gscript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Repository files navigation

 _ _ ___ ___ ___ ___|_|___| |_ | . |_ -| _| _| | . | _| |_ |___|___|_| |_| _|_| |___| |_| 

🎮Play | 📘Features | 🌰Demo | 🔧Install | 👾REPL | 🎉Syntax | 🎁Standard library | 💡Contact Author | 🇨🇳中文


Introduction

This is a statically and strongly typed language written in Go, the syntax of Java and Go is referenced.

Target

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 world

Playground

Online address: https://gscript.crossoverjie.top/

Source code:https://github.com/crossoverJie/gscript-homepage

Features

Demo

Hello world

println("hello world");

Print fibonacci

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());}

Webapp

This is a dynamic web application written in GScript.

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

Source code: https://github.com/crossoverjie/gscript-homepage

YangHui triangle

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:111121133114641151010511615201561

More examples:https://github.com/crossoverJie/gscript/tree/main/example

Install

Binary

Download the latest binaries here

🐳Docker

docker pull crossoverjie/gscript

REPL

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

Run script

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

Build from Source Code

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

REPL

> ./gscript 

Syntax

Primitive

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

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]

any type

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

Class

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);

function

// 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.

Closure

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 

Variable arguments

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 overloading

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

Standard library source code: https://github.com/crossoverJie/gscript/tree/main/internal

Native function

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

Map

Function Definition

classMap{put(anykey,anyvalue){}anyget(anykey){}}

Usage

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);}

StringBuilder

Function Definition

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(){} }

Usage

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);

Strings

Function Definition

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){} }

Usage

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);

http

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");

Contact author

crossoverJie#gmail.com

qrcode_for_gh_3a954a025f10_258.jpg

About

💪🏻This is a statically and strongly typed language written in Go.|GScript 是用 Go 编写的静态、强类型的脚本语言。

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published