有没有支持多个整数大小的Scheme方言?

huangapple go评论62阅读模式
英文:

Are there any dialects of scheme that support multiple integer sizes?

问题

I wish to write a program in Scheme that models the hardware registers of a hypothetical CPU. To this end, I'm going to need signed and unsigned integral datatypes that respect their intended bit widths, for behaviors like overflow and underflow.

Specifically: I'd want {signed,unsigned} x {8-bit,16-bit,32-bit,64-bit}.

But all of my experiences with Scheme so far have been just a single class of signed integers, where the single range is implementation defined (ignoring BIGNUM, for now.)

Is there any existing dialect of Scheme that allows programmers -- possibly via some prefix in front of the literal -- to say e.g. "treat this value as an exact 16-bit unsigned value"?

I would also consider other lispy languages, beyond the Schemes. I just need to know if there is some established syntax for accomplishing the above.

英文:

I wish to write a program in Scheme that models the hardware registers of a hypothetical CPU. To this end, I'm going to need signed and unsigned integral datatypes that respect their intended bit widths, for behaviors like overflow and underflow.

Specifically: I'd want {signed,unsigned} x {8-bit,16-bit,32-bit,64-bit}.

But all of my experiences with Scheme so far have been just a single class of signed integers, where the single range is implementation defined (ignoring BIGNUM, for now.)

Is there any existing dialect of Scheme that allows programmers -- possibly via some prefix in front of the literal -- to say e.g. "treat this value as an exact 16-bit unsigned value"?

I would also consider other lispy languages, beyond the Schemes. I just need to know if there is some established syntax for accomplishing the above.

答案1

得分: 2

这非常依赖于实现,除非您想在所有地方使用模运算。Kawa Scheme支持它们,具有其类型注释和JVM原始整数类型。例如:

#|:kawa:1|# (define (+/u16 a::ushort b::ushort) ::ushort (+ a b))
#|:kawa:2|# (+/u16 65535 50)
49
#|:kawa:3|# (->ushort 500) ; 将文字整数强制转换为ushort
500
#|:kawa:4|# (->ushort 65537) ; 进行范围检查
/dev/tty:9:11: 警告 - 整数65536不在ushort的范围内
1
#|:kawa:5|# (as ushort 65537) ; 但这种形式是安静的
1
#|:kawa:6|# (ushort? -10)
#f

当然,许多Scheme支持SRFI-4同类数值向量用于存储固定宽度类型的数组,但它们不提供任何与之相关的算术运算。当然,如果您想将一组寄存器表示为一组,这仍然很有用。

英文:

This is very much going to be implementation dependent, unless you want to use modular arithmetic everywhere. Kawa Scheme supports them, with its type annotations and JVM primitive integer types. For example:

#|:kawa:1|# (define (+/u16 a::ushort b::ushort) ::ushort (+ a b))
#|:kawa:2|# (+/u16 65535 50)
49
#|:kawa:3|# (->ushort 500) ; Coerce a literal integer to a ushort
500
#|:kawa:4|# (->ushort 65537) ; does range checking
/dev/tty:9:11: warning - integer 65536 not in range of ushort
1
#|:kawa:5|# (as ushort 65537) ; this form however is quiet
1
#|:kawa:6|# (ushort? -10)
#f

And of course many Schemes supports SRFI-4 Homogenous Numeric Vectors for storing arrays of fixed-width types, but that doesn't come with any arithmetic operations on them. Still useful if you want to represent a set of registers as one, of course.

答案2

得分: 1

Scheme有多种数字类型,但没有受寄存器宽度限制的。如果你使用一个具有完整数字塔的Scheme实现,你应该能够模拟这些类型。

#!r6rs
(import (rnrs base)
        (rnrs arithmetic bitwise))
    
(define (get-mask width)
  ;; simple to make a table, but I don't care for speed
  (- (bitwise-arithmetic-shift-left 1 width) 1))

(define (binary-add width carry n1 n2)
  (define mask (get-mask width))
  (define res (+ carry n1 n2))
  (define new-carry (> res mask))
  (define res-truncated (bitwise-and mask res))
  (values res-truncated new-carry))

(binary-add 8 1 128 128)
; ==> 1
; ==> #t

你可以选择将值封装在盒子中,或者将标志设置为副作用,但这些只是具有不同优缺点的设计决策。例如,我想象你可能希望将一个更大的数字(如“eax”寄存器)传递给只关心每个值的前16位的操作,就像真实处理器一样。

英文:

Scheme has several numeric types, but none are limited by register width. When that said if you have a Scheme implementation with a full numeric tower you should be able to simulate those types.

#!r6rs
(import (rnrs base)
        (rnrs arithmetic bitwise))
    
(define (get-mask width)
  ;; simple to make a table, but I don't care for speed
  (- (bitwise-arithmetic-shift-left 1 width) 1))

(define (binary-add width carry n1 n2)
  (define mask (get-mask width))
  (define res (+ carry n1 n2))
  (define new-carry (> res mask))
  (define res-truncated (bitwise-and mask res))
  (values res-truncated new-carry))

(binary-add 8 1 128 128)
; ==> 1
; ==> #t

You might choose to wrap your values in boxes or that flags should be side effects, but these are just design decisions that have different pros and cons. Eg. I do imagine you do want to pass a bigger number eg. the "eax" register to an operation that only cares about the 16 first bits of each value, just like a real processor does

huangapple
  • 本文由 发表于 2023年5月14日 08:15:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76245343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定