当前位置:

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

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

前言先带来日常的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;

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

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    业界资讯 语言 运算符
    相关文章 更多
    编程语言的编程模型
    编程语言的编程模型

    编程模型涵盖面向过程的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电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。