当前位置:

首页 > 业界资讯 > 手写编程语言-实现运算符重载

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

前言先带来日常的GScript更新:新增了可变参数的特性,语法如下: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);得益于可变参数,所以新增了格式化字符串的内置函数://forma

前言

先带来日常的 GScript 更新:新增了可变参数的特性,语法如下:

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

得益于可变参数,所以新增了格式化字符串的内置函数:

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

下面重点看看 GScript 所支持的运算符重载是如何实现的。

使用

运算符重载其实也是多态的一种表现形式,我们可以重写运算符的重载函数,从而改变他们的计算规则。

println(100+2*2);

以这段代码的运算符为例,输出的结果自然是:104.

但如果我们是对两个对象进行计算呢,举个例子:

class Person{
int age;
Person(int a){
age = a;
}
}
Person p1 = Person(10);
Person p2 = Person(20);
Person p3 = p1+p2;

这样的写法在 Java/Go 中都会报编译错误,这是因为他们两者都不支持运算符重载;

但 Python/C# 是支持的,相比之下我觉得 C# 的实现方式更符合 GScript 语法,所以参考 C# 实现了以下的语法规则。

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

有几个硬性条件:

  • 函数名必须是operator
  • 名称后跟上运算符即可。

目前支持的运算符有:+-*/   == != < <= > >=

实现

以前在使用 Python 运算符重载时就有想过它是如何实现的?但没有深究,这次借着自己实现相关功能从而需要深入理解。

其中重点就为两步:

  • 编译期间:记录所有的重载函数和运算符的关系。
  • 运行期:根据当前的运算找到声明的函数,直接运行即可。

第一步的重点是扫描所有的重载函数,将重载函数与运算符存放起来,需要关注的是函数的返回值与运算符类型。

// OpOverload 重载符
type OpOverload struct {
function*Func
tokenType int
}

// 运算符重载自定义函数
opOverloads []*symbol.OpOverload

在编译器中使用一个切片存放。

而在运行期中当两个入参类型相同时,则需要查找重载函数。

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

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

查找方式就是通过编译期存放的数据进行匹配,拿到重载函数后自动调用便实现了重载。

感兴趣的朋友可以查看相关代码:

  • 编译期: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;

就不如下面这种直观,所以有利有弊吧,多一个选项总不是坏事。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
业界资讯 语言
相关文章 更多
编程语言的编程模型
编程语言的编程模型

编程模型涵盖面向过程的C语言、面向对象的Ruby、基于栈的PostScript、基于规则的Prolog、基于原型的Lua、函数式的Erlang/Haskell及混合模型的Scala/Clojure。类型系统区分强类型与弱类型、动态类型与静态类型,元编程允许运行时操作代码,提升表达力。

元编程的思想是一种新的编程细想吗
元编程的思想是一种新的编程细想吗

元编程是指编写程序生成数据或代码供运行时使用,其核心是用程序构造新程序。在JavaScript中,元程序表现为函数,可生成新函数或扩展功能。元编程是函数式编程的扩展,通过反射和代码生成增强灵活性与抽象能力。

编程,还是编程
编程,还是编程

编程思想决定软件设计,优秀软件因理念通俗易懂而广受欢迎。编程语言正在趋向自然语言,极大降低人机沟通门槛。代码能够表现规律与标准,未来或将主导整个世界的运行,甚至统治一切,成为人类社会的全新秩序。

编程之道
编程之道

编程之道是程序的源头,产生机器语言、汇编语言等,体现于空间与时间的阴阳。遵循道能高效编程,违背道则陷入混乱。大师传授道,强调设计、编码、维护、管理中的哲理。硬件依赖软件,软件依赖道。

【编程】编程思想
【编程】编程思想

编程思想是用计算机解决实际问题的思维方式。其发展经历了过程性、结构性和面向对象三个阶段。理解编程思想比掌握具体技术更重要,能够一通百通。学习应循序渐进,着重体会思想精髓。

编程范式
编程范式

编程范式是编程的思维方式与模型,本质是对计算机系统的抽象。不同语言实现不同模型,如Java面向对象、C语言结构化,而C++支持多范式混合使用,还包括函数式、泛型等范式,灵活适应不同场景。

以前我没学过编程 请问编程从那里学起
以前我没学过编程 请问编程从那里学起

编程语言仅为工具,真正决定高度的是数据结构和算法及计算机底层逻辑理解。建议从C语言入门,打好基本功。根据目标选择深入方向,避免同时学习多门语言。最终目标是学会用程序解决问题,语言只是实践载体。

编程概述
编程概述

编程不是艺术,核心是解决问题,要求精确描述并忽略部分现实。控制复杂性是中心议题,通过降低模块耦合来管理代码。复用已有知识是编程技艺核心,通过简单接口构建可复用的信息块,实现有效积累。

编程技术的发展概论以及编程重用之我见
编程技术的发展概论以及编程重用之我见

计算机编程从机器码演进至模板组装,历经面向过程、对象、切面、接口、服务、配置及模板等阶段,每次转折均聚焦代码复用效率提升,最终趋向“不写代码的编程”即低代码或无代码开发。

Linux编程环境
Linux编程环境

接触Linux编程,首先得摸清它的脾气,理解几个关键点,再熟悉一下手头的工具,才能事半功倍。 一、Linux下的编程环境 在Linux系统的程序设计中,有一些重要特性要特别注意: 1. Linux天生就是多任务系统。同一时刻可以跑很多进程或线程,所以千万别以为你的程序是唯一的实例,同一个用户或不同用

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师
macOS

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

WINDOWS 更多
Windows 10
Windows 10
Windows

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘
Windows/macOS/iOS/Android

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。