foreword
First bring the daily GScript update: the feature of variable parameters has been added. The syntax is as follows:
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);
Thanks to variadic parameters, there are new built-in functions for formatting strings:
//formats according to a format specifier and writes to standard output.
printf(string format, any ...a){}
//formats according to a format specifier and returns the resulting string.
string sprintf(string format, any ...a){}
The following focuses on how the operator overloading supported by GScript is implemented.
use
Operator overloading is actually a form of polymorphism. We can rewrite the overloaded functions of operators to change their calculation rules.
println(100+2*2);
Taking the operator of this code as an example, the output result is naturally: 104.
But what if we were computing on two objects, for example:
class Person{
int age;
Person(int a){
age = a;
}
}
Person p1 = Person(10);
Person p2 = Person(20);
Person p3 = p1+p2;
This way of writing will report a compilation error in Java/Go
, because neither of them supports operator overloading;
But Python/C#
is supported. In contrast, I think the implementation of C#
is more in line with the GScript
syntax, so refer to C# to implement the following grammar rules.
Person operator + (Person p1, Person p2){
Person pp = Person(p1.age+p2.age);
return pp;
}
Person p3 = p1+p2;
println("p3.age="+p3.age);
assertEqual(p3.age, 30);
There are several hard conditions:
- The function name must be
operator
- The name is followed by an operator.
Currently supported operators are: +-*/ == != < <= > >=
accomplish
When I used the Python
operator overloading, I thought about how it is implemented? But I didn't go into it. This time I need to understand it by implementing the relevant functions by myself.
The focus is on two steps:
- During compilation: record all overloaded function and operator relationships.
- Runtime: Find the declared function according to the current operation and run it directly.
The focus of the first step is to scan all overloaded functions and store the overloaded functions and operators. What needs to be paid attention to is the return value of the function and the type of the operator.
// OpOverload 重载符
type OpOverload struct {
function *Func
tokenType int
}
// 运算符重载自定义函数
opOverloads []*symbol.OpOverload
Use a slice for storage in the compiler.
At runtime, when two input parameters are of the same type, you need to find overloaded functions.
// GetOpFunction 获取运算符重载函数
// 通过返回值以及运算符号(+-*/) 匹配重载函数
func (a *AnnotatedTree) GetOpFunction(returnType symbol.Type, tokenType int) *symbol.Func {
for _, overload := range a.opOverloads {
isType := overload.GetFunc().GetReturnType().IsType(returnType)
if isType && overload.GetTokenType() == tokenType {
return overload.GetFunc()
}
}
return nil
}
The search method is to match the data stored at compile time. After getting the overloaded function, it is automatically called to realize the overloading.
Interested friends can view the relevant code:
- Compile time: https://github.com/crossoverJie/gscript/blob/ae729ce7d4cf39fe115121993fcd2222716755e5/resolver/type_scope_resolver.go#L127
- Runtime: https://github.com/crossoverJie/gscript/blob/499236af549be47ff827c6d55de1fc8e5600b9b3/visitor.go#L387
Summarize
Operator overloading is actually not a commonly used feature; because it changes the semantics of the operator, for example, it is obviously addition but is written as subtraction in the overloaded function.
This can make the code hard to read, but in some cases we would very much like the language itself to support operator overloading.
For example, a third-party precision library commonly used in Go decimal.Decimal
, can only use functions such as d1.Add(d2)
when the operation is complicated, when the operation is complicated:
a5 = (a1.Add(a2).Add(a3)).Mul(a4);
a5 = (a1+a2+a3)*a4;
It is not as intuitive as the following, so there are pros and cons, and one more option is not a bad thing.
GScript source code:
https://github.com/crossoverJie/gscript
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。