内置函数在解释器中存放在builtins 哈希表中

var builtins = map[string]*object.Builtin{"len": &object.Builtin{Fn: func(args ...object.Object) object.Object {if len(args) != 1 {return newError("wrong number of arguments. got=%d, want=1", len(args))}switch arg := args[0].(type) {case *object.String:return &object.Integer{Value: int64(len(arg.Value))}case *object.Array:return &object.Integer{Value: int64(len(arg.Elements))}default:return newError("argument to `len` not supported, got %s", args[0].Type())}},

作者在这一章写了好多莫名奇妙的逻辑…
比如上面的内置函数,明明修改一下返回值即可作为编译器的参照,但是又要重写一遍,还拿切片来维护…

其实内置函数的实现很简单的,当遇到函数调用,分辨是定义函数还是内置函数,进行不同调用即可;

怎么分辨呢?编译器解析到ast.Identifier 时会查找符号表,得到当前变量的作用范围,如果是GlobalScope,c.emit(code.OpGetGlobal, s.Index) 而内置函数和普通函数的区别就在这儿!

case *ast.Identifier:symbol, ok := c.symbolTable.Resolve(node.Value)if !ok {return fmt.Errorf("undefined variable %s", node.Value)}c.loadSymbol(symbol)func (c *Compiler) loadSymbol(s Symbol) {switch s.Scope {case GlobalScope:c.emit(code.OpGetGlobal, s.Index)case LocalScope:c.emit(code.OpGetLocal, s.Index)case BuiltinScope:c.emit(code.OpGetBuiltin, s.Index)}
}

我们应该设置新的Scope关于Builtin 来识别Builtin Function

const (// ...OpGetBuiltin
)var Definitions = map[Opcode]*Definition {// ...OpGetBuiltin: {"OpGetBuiltin", []int{1}},
}

OpGetBuiltin 也要有参数位,因为内置函数会有不同的参数要求;

虚拟机执行如下:

 case code.OpCall:numArgs := int(code.ReadUint8(ins[ip+1:]))vm.currentFrame().ip += 1err := vm.executeCall(int(numArgs))if err != nil {return errcase code.OpGetBuiltin:builtinIndex := code.ReadUint8(ins[ip+1:])vm.currentFrame().ip += 1definition := object.Builtins[builtinIndex]err := vm.push(definition.Builtin)if err != nil {return err}func (vm *VM) executeCall(numArgs int) error {callee := vm.stack[vm.sp-1-numArgs]switch callee := callee.(type) {case *object.CompiledFunction:return vm.callFunction(callee, numArgs)case *object.Builtin:return vm.callBuiltin(callee, numArgs)default:return fmt.Errorf("calling non-function and non-built-in")}
}func (vm *VM) callBuiltin(builtin *object.Builtin, numArgs int) error {args := vm.stack[vm.sp-numArgs : vm.sp]result := builtin.Fn(args...)vm.sp = vm.sp - numArgs - 1if result != nil {vm.push(result)} else {vm.push(nil)}return nil
}

其实和正常的调用一样,只不过内置函数调用的是提供好的接口,定义函数则是模拟调用过程!

(当然了,内置函数要先在REPL 前于全局符号表中定义方可使用)

(七)Builtin Function相关推荐

  1. warning incompatible implicit declaration of built-in function 'printf'

    利用arm交叉编译器编译一个简单的c程序出现  warning :incompatible implicit declaration of built-in function 'printf'错误 原 ...

  2. FastApi报错 Invalid args for response field! Hint: check that <built-in function id> 。。。解决方法

    今天运行项目发现运行报错,错误内容是: Invalid args for response field! Hint: check that <built-in function id> i ...

  3. Builtin function

    发现 Builtin function 可以用来计算十进制数中1的个数:返回1的个数是奇数还是偶数:返回开头0的个数:返回结尾0的个数. 参考链接: // C program to illustrat ...

  4. [Warning] incompatible implicit declaration of built-in function ‘memset‘

    [Warning] incompatible implicit declaration of built-in function 'memset' 原因是memset第一个参数是void * 类型,我 ...

  5. MATLAB笔记:一些自嵌函数/built-in function

    文章目录 strvcat(不推荐)垂直串联字符串 ind2sub 索引值转换为下标 squeeze gcd(求最大公约数) fullfile physconst typecast(在不更改基础数据的情 ...

  6. set built-in function

    集合类型 集合对象是一组无序排列的可哈希的值,集合可以作为字典的键.因为集合是无序的,不可以为集合创建索引或执行切片操作,也没有键可以用来获取元素的值. 集合有两种不同的类型,可变集合和不可变集合.可 ...

  7. warning: incompatible implicit declaration of built-in function ‘exit’

    出现这个错误,一般是程序中某个函数没有include相关的文件. EG. 出现这个错误是因为要使用exit()应该包含stdlib.h文件 转载于:https://www.cnblogs.com/wi ...

  8. Python编程核心内容 ---- Function(函数)

    什么"大事"呢?下面将要介绍Python编程的核心内容之一--函数. 对于Python编程,函数的重要性不言而喻.重要的事情讲三遍:函数实在是太重要,太关键了. 引入函数 之前,我 ...

  9. php七牛分片上传_ThinkPHP实现JavaScript上传大视频到七牛云实例

    1.通过Composer安装七牛云PHP SDK,官方文档 2.后端核心代码如下: use Qiniu\Auth as Auth; use Qiniu\Config; use Qiniu\Storag ...

最新文章

  1. 管理-Tomcat和Resin如何配置对指定后缀文件(如:.pptx)下载支持
  2. Binder相关面试总结(七):AIDL内部的实现原理是什么
  3. 【云周刊】第132期:走近40+世界级AI专家!第三届中国人工智能大会资料分享...
  4. Vagrant配置虚拟机
  5. 一文详解神经网络模型
  6. The fall of RNN / LSTM
  7. 翻币问题pascal程序
  8. 神经网络 | 网络优化-线性神经网络-delta学习规则-梯度下降法(线性神经网络-异或问题Python源代码)
  9. oracle里查询表的语句,Oracle查询用户所有表的语句
  10. 把VS Code打造成Java开发IDE,也挺爽!
  11. sublime配置python编译环境及代码补全功能
  12. 函数作为参数传递至函数内部进行调用
  13. more than one device and emulator
  14. mysql where range_MYSQL explain详解之range
  15. C语言-数组练习题(附答案)
  16. STM32中AD采样的三种方法分析
  17. 干货 | 携程Elasticsearch数据同步实践
  18. croeldraw基本知识点
  19. Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o).
  20. 【Redis】布隆过滤器

热门文章

  1. scala字符串转int_如何在Scala中将十六进制字符串转换为int?
  2. 现行大数据框架技术思想鼻祖--不得不看的Google三大论文(英文原文)
  3. Web APIs五、BOM操作浏览器
  4. android 拍照插件,拍照录像,android原生插件
  5. plsql 导出用户对象和导出表的区别
  6. Linux入门-常见指令
  7. 宅家娱乐的定制假期!用三星电视体验超强影像力和游戏力
  8. 统计模式识别的原理与方法
  9. resultType 使用方法 笔记
  10. In App Purchases(IAP 应用程序內购买): 完全攻略 (2合1)