源链接:https://www.axa6.com/zh/type-definition-of-aq-virtual-machine
简介
由于不同的系统
、硬件
等外部条件对于内存
有不同的支持和定义,因此为了使AQ虚拟机
满足跨平台运行的要求,设计统一的类型
标准是必不可少的。本文对于AQ虚拟机
的类型
进行了定义和规范,以确保在不同系统上的AQ虚拟机
均能正常运行。
设计思路
首先,为实现类型
的精简和更高的运行效率,对于原生类型
(不通过代码定义,虚拟机直接支持的类型
)的设计应尽可能少。因此对于相关的复杂类型,如枚举
、结构体
等,我们在编译器
层面开发,减少虚拟机
的类型
数量和复杂度
。
根据
memory.h
中对于AqvmMemory_Memory
中type
的定义,每一个uint8_t
存储2
个类型
,因此类型
的数量应在0x00
-0x0F
(16个)之间。
其次,通过对于其它编程语言
的类型
的研究,总结了常见的类型
,我们设计了以下几种类型
,以便于在虚拟机
的性能与简洁达到平衡。
- null - 空类型
- byte -
1
字节有符号整数类型 - int -
4
字节有符号整数类型 - long -
8
字节有符号整数类型 - float -
4
字节单精度浮点类型 - double -
8
字节双精度浮点类型
最后,我们为类型
设计了详细的标准
,以确保AQ虚拟机
能够实现跨平台
运行。
为了减少
虚拟机
的类型定义,无符号类型
将在编译器
层面被实现。
其它编程语言
的类型
定义
为了使AQ
的类型
更加广泛且易于被开发人员掌握,我们参考了现有的常见的编程语言
的类型
定义。
此处定义下文中的基础类型
为整数、浮点数、空类型等一般的数据
类型。其承担基本的数据存储工作或具有特殊的意义。
C
现行的C
标准是ISO/IEC 9899:2018 Information technology — Programming languages — C
。由于该标准版权归属ISO(国际标准化组织)
和IEC(国际电工委员会)
,因此为避免版权纠纷,我们就其中的类型
定义进行了归纳总结。下同。
官方网址:https://www.iso.org/standard/74528.html
_Bool
- 声明为_Bool
类型的对象足够大以存储值0
和1
。(unsigned) char
- 字符类型。声明为类型char
的对象足够大,可以存储基本执行字符集的任何成员。如果基本执行字符集的成员存储在char
对象中,则其值保证为非负值。如果任何其他字符存储在一个字符对象中,则结果值为implementation-defned
,但应在该类型中可以表示的值范围内。signed char
- 有符号字符类型。short int
- 扩展有符号整数类型。unsigned short int
- 扩展无符号整数类型。int
- 扩展标准有符号整数类型。unsigned int
- 标准无符号整数类型。long int
- 扩展有符号整数类型。unsigned long int
- 扩展无符号整数类型。long long int
- 扩展有符号整数类型。unsigned long long int
- 扩展无符号整数类型。float
- 浮点类型。float
类型的值集是double
类型的一组值的子集。double
- 浮点类型。double
类型的值集是long double
类型的一组值的子集。long double
- 浮点类型。void
-void
类型包含一组空值;它是一个不完整的对象类型,无法实现。
除此之外,C
还有其它非基础类型
,如枚举
类型(enum
类型),指针类型等。在虚拟机
的设计中不作讨论。
C++
及其它C
变种
现行的C++
标准是ISO/IEC 14882:2020 Programming languages — C++
。由于C++
及其它C
变种与C
的类型基本一致,因此不再列出。
Python
最新的Python
正式版本是3.12.4
。在Python 3.12.4 Documentation
中的内置类型
记载了Python
解释器中内置的标准类型。
其中的主要内置类型有数字
、序列
、映射
、类
、实例
和异常
。由于篇幅原因,在此对于除基础类型
外的内容不作讨论。
源链接:https://docs.python.org/zh-cn/3/library/stdtypes.html
int
- 整数整数
具有无限的精度。未经修饰的整数字面(包括十六进制、八进制和二进制数)产生整数。float
- 浮点数浮点数
通常在C
中使用double
实现。包含小数点
或指数符号
的数值字面产生浮点数
。complex
- 复数 复数有实数部分
和虚数部分
,每一部分都是浮点数
。在数值字面后面加上j
或J
,可以得到一个虚数
(实数部分为零的复数
),将其与整数
或浮点数
相加,可以得到一个包含实数部分
和虚数部分
的复数
。bool
- 布尔型布尔型
也是整数
的一种子类型
。代表真值的布尔对象。bool
类型只有两个常量实例:True
和False
。list
- 列表列表
是可变序列
,通常用于存放同类项目的集合
(其中精确的相似程度将根据应用而变化)。tuple
- 元组元组
是不可变序列
,通常用于储存异构数据的多项集
(例如由enumerate()
内置函数所产生的二元组
)。元组
也被用于需要同构数据的不可变序列
的情况(例如允许存储到set
或dict
的实例)。range
-range
类型表示不可变
的数字序列
,通常用于在for
循环中循环指定的次数。str
- 文本序列类型 在Python
中处理文本数据是使用str
对象,也称为字符串
。字符串
是由Unicode
码位构成的不可变序列
。bytes
-bytes
对象是由单个字节构成的不可变序列
。由于许多主要二进制协议都基于ASCII
文本编码,因此bytes
对象提供了一些仅在处理ASCII
兼容数据时可用,并且在许多特性上与字符串
对象紧密相关的方法
。bytearray
-bytearray
对象是bytes
对象的可变对应物。memoryview
- 内存视图memoryview
对象允许Python
代码访问一个对象的内部数据,只要该对象支持缓冲区协议
而无需进行拷贝。set
- 集合类型set
对象是由具有唯一性的hashable
对象所组成的无序多项集
。 常见的用途包括成员检测、从序列中去除重复项以及数学中的集合类计算,例如交集
、并集
、差集
与对称差集
等等。set
类型是可变的,其内容可以使用add()
和remove()
这样的方法来改变。由于是可变类型
,它没有哈希值
,且不能被用作字典
的键
或其他集合
的元素
。frozenset
- 集合类型frozenset
类型是不可变
并且为hashable
,其内容在被创建后不能再改变,因此它可以被用作字典
的键
或其他集合
的元素
。dict
- 映射类型mapping
对象会将hashable
值映射到任意对象。映射
属于可变对象
。目前仅有一种标准映射类型字典
。GenericAlias
-GenericAlias
对象通常是通过抽取
一个类
来创建的。它们最常被用于容器类
,如list
或dict
。举例来说,list[int]
这个GenericAlias
对象是通过附带int
参数抽取list
类来创建的。GenericAlias
对象的主要目的是用于类型标注
。union
-联合对象
包含了在多个类型对象
上执行| (按位或)
运算后的值。 这些类型主要用于类型标注
。与typing.Union
相比,联合类型
表达式可以实现更简洁的类型提示语法。
Java
JVM(Java虚拟机)
的规范
是The Java® Virtual Machine Specification
,最新版本是Java SE 22 Edition
,发布日期为2024-02-09
。相较与其它语言的编译器
层面的类型定义
,JVM
的情况更符合虚拟机
的设计。同时JVM
的类型
分为基元类型
和引用类型
,由于虚拟机
开发需要,选择了基元类型
进行讨论。
除此之外,Java
还有一份规范
是The Java Language Specification, Java SE 22 Edition
,HTML
链接:https://docs.oracle.com/javase/specs/jls/se22/html/index.html PDF
链接:https://docs.oracle.com/javase/specs/jls/se22/jls22.pdf 。由于虚拟机
开发的特殊需要,因此在本文选择研究JVM
的类型定义
而非Java
语言的类型定义
源链接(HTML):https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-2.html#jvms-2.3
源链接(PDF):https://docs.oracle.com/javase/specs/jvms/se22/jvms22.pdf
byte
- 整数类型 其值是8
位有符号二进制补码整数,其默认值为零
。从-128
至127
(-27至27 - 1),包括在内。short
- 整数类型 其值为16
位有符号二进制补码整数,其默认值为零
。从-32768
至32767
(-215至215 - 1),包括在内。int
- 整数类型 其值为32
位有符号二进制补码整数,其默认值为零
。从-2147483648
至2147483647
(-231至231 - 1),包括在内。long
- 整数类型 其值为64
位有符号二进制补码整数,其默认值为零
。从-9223372036854775808
至9223372036854775807
(-263至263 - 1),包括在内。char
- 整数类型 其值为16
位无符号整数,表示基本多语言平面中的Unicode
码位,编码为UTF-16
,其默认值为null
码位 (\u0000
)。从0
到65535
。float
- 浮点类型 其值完全符合32
位IEEE 754 binary32格式,默认值为正零
。double
- 浮点类型 其值与64
位IEEE 754 binary64格式的值完全一致,默认值为正零
。
详细标准
类型定义
复杂的类型会有编译器
处理以保证虚拟机
的简洁和效率,对于简单的类型,则会被虚拟机
直接支持。
以下是AQ虚拟机
定义的6
种基本类型有:
未直接支持的类型包括
无符号整数
,内存地址(指针)
,字符串
等。这些类型将在编译器
层面得到实现。对于虚拟机
来说,这些类型被间接实现。
-
null
-0x00
- 空类型
空类型仅代表未知类型或无需使用的类型(例如:无返回)。没有长度。 -
byte
-0x01
-1
字节(8
位)有符号整数类型
采用二进制补码存储。一般用于存储bool
或char
。从-128
至127
(-27至27 - 1),包括在内。 -
int
-0x02
-4
字节(32
位)有符号整数类型
采用二进制补码存储。从-2147483648
至2147483647
(-231至231 - 1),包括在内。 -
long
-0x03
-8
字节(64
位)有符号整数类型
采用二进制补码存储。内存地址(指针)
也用此存储。其值为64
位有符号二进制补码整数,其默认值为零
。从-9223372036854775808
至9223372036854775807
(-263至263 - 1),包括在内。 -
float
-0x04
-4
字节(32
位)单精度浮点类型
采用ISO/IEC 60559 Information technology — Microprocessor Systems — Floating-Point arithmetic
标准。 -
double
-0x05
-8
字节(64
位)双精度浮点类型
采用ISO/IEC 60559 Information technology — Microprocessor Systems — Floating-Point arithmetic
标准。
补码
定义
补码
是计算机中有符号数的表示方法。
方法
正数
和0
的补码
就是该数字本身再补上最高比特0。负数
的补码
则是将其绝对值按位取反再加1。
浮点数标准
定义
浮点数标准
采用ISO/IEC 60559 Information technology — Microprocessor Systems — Floating-Point arithmetic
标准。该标准又称IEEE二进制浮点数算术标准(IEEE 754)
官方网址:https://www.iso.org/standard/80985.html
方法
浮点数
的实际值
,等于符号位
乘以指数偏移值
再乘以分数值
。详细定义见ISO/IEC 60559 Information technology — Microprocessor Systems — Floating-Point arithmetic
标准。
32
位浮点数
比特长度 | 名称 | 比特编号 |
---|---|---|
1 | 符号位 | 31 |
8 | 数字 | 30至23偏正值(实际的指数大小+127) |
23 | 有效数字 | 22至0位编号(从右边开始为0) |
64
位浮点数
比特长度 | 名称 | 比特编号 |
---|---|---|
1 | 符号位 | 63 |
11 | 数字 | 62至52偏正值(实际的指数大小+1023) |
52 | 有效数字 | 51至0位编号(从右边开始为0) |
types.h
完整代码:
对于类型
同样有相关代码。以下是types.h
的代码:
// Copyright 2024 AQ author, All Rights Reserved.
// This program is licensed under the AQ License. You can find the AQ license in
// the root directory.
#ifndef AQ_AQVM_MEMORY_TYPES_H_
#define AQ_AQVM_MEMORY_TYPES_H_
#include <stdint.h>
// null - 0x00 - null type
// The null type simply represents an unknown type or a type that is not needed
// (e.g., returns nothing). Has no length.
typedef void aqnull;
// byte - 0x01 - 1 byte (8-bit) signed integer type
// Using two's complement storage. Generally used to store bool or char. From
// -128 to 127 (-2^7 to 2^7 - 1), inclusive.
typedef int8_t aqbyte;
// int - 0x02 - 4-byte (32-bit) signed integer type
// Stored in two's complement notation. From -2147483648 to 2147483647 (-2^31 to
// 2^31 - 1), inclusive.
typedef int aqint;
// long - 0x03 - 8-byte (64-bit) signed integer type
// Stored in two's complement notation. From -9223372036854775808 to
// 9223372036854775807 (-2^63 to 2^63 - 1), inclusive.
typedef int64_t aqlong;
// float - 0x04 - 4-byte (32-bit) single-precision floating point type
// Using ISO/IEC 60559 Information technology — Microprocessor Systems —
// Floating-Point arithmetic standard.
typedef float aqfloat;
// double - 0x05 - 8-byte (64-bit) double-precision floating point type
// Using ISO/IEC 60559 Information technology — Microprocessor Systems —
// Floating-Point arithmetic standard.
typedef double aqdouble;
// The part beyond 0x05 and within 0x0F is currently designated as a reserved
// type. The part beyond 0x0F cannot be used because it exceeds the 4-bit size
// limit.
#endif
我们正在更加努力地开发
AQ虚拟机
。如果您想了解更多信息或参与开发工作,请关注我们的官网:https://www.axa6.com 和 Github:https://github.com/aq-org/AQ。
本文章基于AQ License:https://github.com/aq-org/AQ/blob/main/LICENSE 发布,如有需要,请根据AQ License进行改编或转载。