当前位置: 首页 > 科技观察

手写编程语言-实现运算符重载

时间:2023-03-21 10:29:48 科技观察

前言首先带来GScript每日更新:新增可变参数特性,语法如下:intadd(strings,int...num){println(s);整数总和=0;for(inti=0;i>=实现在使用Python运算符重载之前,你有没有想过它是如何实现的?但我没有深究。这次需要通过自己实现相关功能来深入理解。重点在两个步骤:编译时:记录所有重载函数和运算符的关系。运行时:根据当前运行找到声明的函数,直接运行。第一步的重点是扫描所有重载函数,存储重载函数和运算符,注意函数的返回值和运算符类型。//OpOverloadoverloadtypeOpOverloadstruct{function*FunctokenTypeint}//运算符重载自定义函数opOverloads[]*symbol.OpOverload在编译器中存储在一个slice中。但是,当两个输入参数在运行时是同一类型时,就需要找到重载的函数。//GetOpFunction获取运算符重载函数//通过返回值和运算符号(+-*/)匹配重载函数func(a*AnnotatedTree)GetOpFunction(returnTypesymbol.Type,tokenTypeint)*symbol.Func{for_,overload:=rangea.opOverloads{isType:=overload.GetFunc().GetReturnType().IsType(returnType)ifisType&&overload.GetTokenType()==tokenType{returnoverload.GetFunc()}}returnnil}搜索方法是对编译时存储的数据进行匹配,得到重载函数后自动调用重载函数,实现重载。感兴趣的朋友可以查看相关代码:编译期:https://github.com/crossoverJie/gscript/blob/ae729ce7d4cf39fe115121993fcd2222716755e5/resolver/type_scope_resolver.go#L127运行期:https://github.com/crossoverJie/gscript/blob/499236af549be47ff827c6d55de1fc8e5600b9b3/visitor.go#L387总结运算符重载其实不是一个常用的函数;因为它会改变运算符的语义,例如加法在重载函数中写成减法。这会使代码难以阅读,但在某些情况下,我们确实希望语言支持运算符重载。比如Go中常用的第三方精度库decimal.Decimal,在进行计算时只能使用d1.Add(d2)等函数。计算复杂时:a5=(a1.Add(a2).Add(a3)).Mul(a4);a5=(a1+a2+a3)*a4;不像下面这么直观,所以有利也有弊。多一个选择不是坏事。