foreword
It is said that the three major romances of programmers are: operating system, compilation principle, graphics; the last graphics is indeed a specific professional field, which we can hardly touch, so it is more suitable for me to switch to the network, and finally plus a database.
If these four technologies can be mastered, wouldn't it be in the IT industry, and the Internet industry has become more and more sluggish in recent years, and the lower-level technologies are less likely to be replaced; so in order to give their 30+ The crisis leaves some way out. Since the first half of this year, I have gradually started to learn the principles of compilation from scratch.
The hard work pays off. After nearly a month of night battles, I have to rest every night at the urging of my wife. I have overcome the urge to give up several times in the middle, and finally I have completed a preview version of GScript .
The preview version means that the syntax structure and overall design are basically completed, and subsequent updates will not change this part of the content, but there are still some easy-to-use features missing.
characteristic
Let's first look at the reserved part, how GScript is written hello world
.
hello_world.gs:
println("hello world");
❯ gscript hello_world.gs
hello world
After talking nonsense, let's focus on the features supported by GScript
.
Each of these features is highlighted below.
example
In addition to the hello world just mentioned, let's look at another example code that is often demonstrated 打印斐波那契数列
.
void 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 < 5; i++){
println(f());
}
The output is as follows:
0
1
1
2
3
The overall writing is similar to the official recommendation of Go: https://go.dev/play/p/NeGuDahW2yP
// fib returns a function that returns
// successive Fibonacci numbers.
func fib() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
func main() {
f := fib()
// Function calls are evaluated left-to-right.
fmt.Println(f(), f(), f(), f(), f())
}
They are all implemented through closure variables, and it also shows the use of closures and functions GScript
The usage of closures will be introduced in detail later.
grammar
The syntax of GScript
dd21fcc60407a21792960f52e1f6b339--- is similar to the common Java/Go
, so it is very easy to get started.
basic type
Let's take a look at the basic types first, currently supports int/string/float/bool
four basic types and nil
special type.
The variable declaration syntax is similar to Java
:
int a=10;
string b,c;
float e = 10.1;
bool f = false;
Personally, I think putting the type in the front will make the code read more clearly, of course, this is also a personal preference.
array
// 声明并初始化
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);
In fact, strictly speaking, this is not an array, because its bottom layer is implemented by Go
slice, so it can be dynamically expanded.
Take this code as an example:
int[] a=[2]{};
println("数组大小:"+len(a));
a = append(a,1);
println("数组大小:"+len(a));
println(a);
a[0]=100;
println(a);
output:
数组大小:2
数组大小:3
[<nil> <nil> 1]
[100 <nil> 1]
Class
Class support is very important and is the basis for implementing object-oriented. At present, object-oriented has not been fully implemented, only the encapsulation of data and functions has been implemented.
class ListNode{
int value;
ListNode next;
ListNode(int v, ListNode n){
value =v;
next = n;
}
}
// 调用构造函数时不需要使用 new 关键字。
ListNode l1 = ListNode(1, nil);
// 使用 . 调用对象属性或函数。
println(l1.value);
By default class
has a no-argument constructor:
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);
Thanks to the implementation of class
, an array of custom types can also be defined in combination with the array just now:
// 大小为 16 的 Person 数组
Person[] personList = [16]{};
function
There are actually two types of functions:
- Ordinary global function.
- class function.
There is no difference in essence, only the scope is different.
// 判断链表是否有环
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);
Here is a function that demonstrates whether the linked list has a ring. As long as there is a basis for the use of other languages, I believe there is no problem in reading it.
add(int a){}
When a function has no return value, it can be declared void or simply ignore the return type.
Closure
I think closures are a very interesting feature that enables very flexible designs and is the foundation of functional programming.
So in GScript
functions exist as first-class citizens; therefore GScript
also supports variables of function type.
The function variable declaration syntax is as follows: 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);
}
The final output is as follows:
0
varInner=21, varExternal=11
1
varInner=22, varExternal=12
=======
0
varInner=21, varExternal=13
1
varInner=22, varExternal=14
func int(int) f2 = f1();
Take this code as an example: f2 is a function type whose return value and input parameters are int; so it can be directly used as a function call in the f2(i)
.
In the example, the closures are assigned to the f2 and f3 variables respectively. The closure data in these two variables are also isolated from each other and do not affect each other. All based on this feature, object-oriented is even implemented.
Regarding the implementation of closures, a separate article will be updated later.
For more examples, please refer to: https://github.com/crossoverJie/gscript/tree/main/example
standard library
Standard library source code: https://github.com/crossoverJie/gscript/tree/main/internal
There are not many standard libraries implemented at present, which is completely manual work; based on the existing syntax and basic data types, almost most data structures can be implemented, so interested friends are also welcome to contribute standard library code; for example Stack
, Set
and other data structures.
MapString
Take this MapString
as an example: the key-value pairs are string
of HashMap
.
int count =100;
MapString m1 = MapString();
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);
}
It is similar to Java
of HashMap
. Of course, his implementation source code is also referenced to HashMap
of jdk1.7.
Since there is currently a Java-likeobject
or ---752df0ee88f422f298bfbed8e07b1072interface{}
in go, if you need to store int, you have to implement a MapInt, but this general type will be implemented soon .
built-in function
int[] a={1,2,3};
// len 返回数组大小
println(len(a));
// 向数组追加数据
a = append(a,4);
println(a);
// output: [1,2,3,4]
// 断言函数,不相等时会抛出运行时异常,并中断程序。
assertEqual(len(a),4);
// 返回 hashcode
int hashcode = hash(key);
Some basic functions are also built-in, of course, this is not implemented by the source code of GScript
, but by the compiler, so it will be a little more troublesome to add; it will be gradually improved in the future, such as built-in related to IO function.
Summarize
At this stage GScript
there are still many functions that are not perfect, such as JSON, network library, more complete grammar check, compilation error information, etc.; now use it to brush LeetCode
still no problem .
From these 65 todos, it can be seen that there is still a long way to go, and my ultimate goal for it is to be able to write a website even if it is a mature language.
Another problem is that there is no integrated development environment. The current development experience is no different from writing code on a whiteboard, so if you have time in the future, try to write a VS Code plugin, at least with syntax highlighting and prompts.
Finally, friends who are interested in GScript
or the compilation principle can add me to WeChat to communicate.
Project source code: https://github.com/crossoverJie/gscript
Download address: https://github.com/crossoverJie/gscript/releases/tag/v0.0.6
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。