2
头图

foreword

In the last article "Finally Implemented a Programming Language of My Own" , I introduced the programming language GScript I wrote. In the article, I mentioned that I hope that I can finally use GScript to develop a website.

So far it has indeed been done, the home page address:

https://gscript.crossoverjie.top/index

It is indeed a bit reluctant to call a website, but it is also a dynamic webpage, because the return is HTML , so at the current stage, as long as it is not too troublesome, you can actually write a "qualified" website, a bit like we used to Java servlet .

The source address of this page is here:
https://github.com/crossoverjie/gscript-homepage

In fact, there are only about 40 lines of code in total:

 class GScript{
    string author;
    string[] features;
    string since;

    GScript(string a, string[] f, string s){
        author = a;
        features = f;
        since = s;
    }
}

func (HttpContext) index(HttpContext ctx){
    string[] features = {"statically", "strongly"};
    GScript gs = GScript("crossoverJie",features, "2022");
    string j = JSON(gs);
    println(j);
    string local = getCurrentTime("Asia/Shanghai","2006-01-02 15:04:05");
    println("local=" + local);
    string html = ^
        <html>
            <title>GScript</title>
            <pre>
                 _     _   
 ___ ___ ___ ___|_|___| |_ 
| . |_ -|  _|  _| | . |  _|
|_  |___|___|_| |_|  _|_|  
|___|             |_|   v0.0.7   

^+ j +^
            </pre>
            <h1>current ^+ local +^</h1>
            <p><a href="https://github.com/crossoverjie/gscript-homepage">GScript-homepace source code</a></p>
        </html>
    ^;
    ctx.HTML(200, html);
}

httpHandle("GET", "/index", index);
string[] args = getOSArgs();
if (len(args) ==3){
    httpRun(":" + args[2]);
}else {
    httpRun(":8000");
}

All are implemented using the standard library provided by GScript , and the built-in HTTP package will be discussed in detail later.

update content

Let's take a look at the key points v0.0.8 what has been updated in this version compared to the previous one.

Because I implemented an http service from the perspective of a developer, and I also used GScript to brush two simple LeetCode; in order to make this process smoother and more in line with the use of a modern language way, so this time really updated a lot of things.

Source code for brushing questions: https://github.com/crossoverJie/gscript/tree/main/example/leetcode

Probably as follows:

  • any type support, simplifying the implementation of the standard library.
  • You can use ^^ to declare multi-line strings, which is convenient for declaring complex strings.
  • More perfect type deduction, fixed the bug that the type could not be deduced in some cases in the previous version.
  • Operator overloading is supported.
  • The basic http package, which can develop http services, can currently respond to JSON and HTML .
  • Added built-in functions: get the current time according to the time zone, get application startup parameters, etc.
  • JSON 's sequence table and query, the syntax level is adapted to XJSON .
  • Fixed a bug that in multiple block nested cases could not be correct return .

In fact, it can be seen from these updates that the last version was only a simple and usable state, and now this version can be used to write complex logic. Of course, there are still some more friendly compilation prompts and runtime errors.

Let’s take a closer look at some of the updates below.

any type

The first is any generic type, which is similar to ---520f0f8d15859178b11527b3319212ff--- in Java and Object interface{} Go, which greatly facilitates us to write some standard libraries.

Taking the built-in hash and len functions as an example, it needs to be implemented for each type, which is very troublesome and unnecessary; now it only needs to be defined once, and the amount of code is directly saved several times.


Similarly, the previously implemented Map only supports storing the string type, but now it can store any type of data.

Friends who are interested in the implementation process of any can share it separately in the future.

operator overloading

Friends who write go or Java should know that neither language can operate on two objects, and the compiler will report an error directly.

But in some special scenarios, it is quite C# to use, so I refer to the syntax of GScript which is also implemented in ---4a8d0e46f7196444278071d3d7670329---.

 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 p1 = Person(10);
Person p2 = Person(20);
Person p3 = p1+p2;
println("p3.age="+p3.age);
assertEqual(p3.age, 30);

The declared function name must be operator , followed by the operator to implement overloading.

The supported operators are: +-*/ < >= <= > == .

JSON support

The current version supports serialization of objects and basic types, but does not support deserialization into objects for the time being, but you can query data through a certain syntax according to JSON string.

Two JSON related functions are built in:

 // return JSON string
string JSON(any a){}
// JSON query with path
any JSONGet(string json, string path){}
 class Person{
    int age;
    string name;
    float weight;
    bool man;
    Person(string n, int a, float w, bool m){
        name = n;
        age = a;
        weight = w;
        man =m;
    }
}
Person p1 = Person("abc",10,99.99,true);
Person p2 = Person("a",11,999.99,false);
string json = JSON(p1);
println(json);
// output:{"age":10,"man":true,"name":"abc","weight":99.99}

Taking this code as an example, calling the JSON function can serialize the object into a JSON string.


 class Person{
    int age;
    string name;
    float weight;
    bool man;
    Person(string n, int a, float w, bool m){
        name = n;
        age = a;
        weight = w;
        man =m;
    }
}
Person p1 = Person("abc",10,99.99,true);
string json = JSON(p1);
println(json);

int age = JSONGet(json, "age");
println(age);
assertEqual(age,10);

Use the JSONGet function to query any data in a JSON string. This function is implemented by adapting XJSON , so the query syntax supported by XJSON can be implemented.

 string j=^{"age":10, "abc":{"def":"def"},"list":[1,2,3]}^;
String def = JSONGet(j, "abc.def");
println(def);
assertEqual(def,"def");
int l1 = JSONGet(j, "list[0]");
println(l1);
assertEqual(l1,1);

string str=^
{
    "name": "bob",
    "age": 20,
    "skill": {
        "lang": [
            {
                "go": {
                    "feature": [
                        "goroutine",
                        "channel",
                        "simple",
                        true
                    ]
                }
            }
        ]
    }
}
^;
String g = JSONGet(str, "skill.lang[0].go.feature[0]");
println(g);
assertEqual(g,"goroutine");

For example, such complex nesting JSON can also obtain data through query syntax.

HTTP package

The HTTP package is the focus of this upgrade. The following functions and classes are provided in the standard library:

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

The specific use process:

  1. Implement your own business logic by defining a function variable.
  2. Register the route.
  3. Start the HTTP service.

In your own handle , you can get the request context through the HttpContext object, and you can get request parameters and response data.
For specific usage examples, please refer to this code.

Summarize

This update is smoother than I expected, because the syntax tree and compiler have been basically implemented and will not be changed much. Now the new feature is nothing more than the implementation of some syntactic sugar at runtime, most of which are manual labor; maybe It's the stimulant effect of freshness, pain and pleasure most of the time.

For example, these two days are mainly to repair the multi-layer block the bug that the statement cannot return correctly when the nesting return statement cannot be returned correctly. The solution, now think about it, there is still too little relevant experience.

Friends who are interested in this bug can like it and share it later.

The focus of the next stage is to organize the compilation information to make the development experience better. After that, I took time to implement the SQL standard library, so that I can be happy CURD .

Finally, I hope that friends who are interested in the project or the compiling principle can download and use it, put forward valuable opinions, and welcome to add me to WeChat to communicate.

v0.0.8 download address:
https://github.com/crossoverJie/gscript/releases/tag/v0.0.8


crossoverJie
5.4k 声望4k 粉丝