--* From sutor@bengals.watson.ibm.com Wed Jan 20 10:58:53 1993 --* Received: from bengals.watson.ibm.com by radical.watson.ibm.com (AIX 3.2/UCB 5.64/900524) --* id AA13148; Wed, 20 Jan 1993 10:58:53 -0500 --* X-External-Networks: yes --* Received: by bengals.watson.ibm.com (AIX 3.1/UCB 5.61/920123) --* id AA23853; Wed, 20 Jan 93 11:01:51 -0500 --* Date: Wed, 20 Jan 93 11:01:51 -0500 --* From: sutor@bengals.watson.ibm.com (Robert Sutor) --* Message-Id: <9301201601.AA23853@bengals.watson.ibm.com> --* To: axc-bug@radical.watson.ibm.com --* Subject: OS/2 has bad memory refs for non-trivial memory schemes current --@ Fixed by: RSS Thu Oct 14 12:45:39 1993 --@ Tested by: none --@ Summary: does not happen anymore -- -- basic.as -- -- Basic Types #assert InBasic #include "aslib.as" #include "builtin.as" --!! These declarations should be redundant export ->: (Tuple Type, Tuple Type) -> Type export Tuple: Type -> Type ++ Type is the type of all data type objects, including itself. Type: with == add ++ -> is the operation which forms mapping types. ((A: Tuple Type) -> (R: Tuple Type)): with apply: (%, A) -> R == add --!! apply(f: %, a: A): R == f a ++ Tuple(S) is the type of n-ary, homogenous products of values in S. ++ E.g. (), (1), (1, 2), (1,3,7,8) are all values of type Tuple Integer. ++ Tuple values are not mutable. Tuple(T: Type): with tuple: (SingleInteger, Pointer) -> % ++ Form a tuple. #: (%) -> SingleInteger ++ The number of components. apply: (%, SingleInteger) -> T ++ 1-origin element slector. == add Rep ==> Record(size: BSInt, values: BArr) import Rep import Builtin: with ArrElt: (BArr, BSInt) -> T tuple(n: SingleInteger,v:Pointer):%== per [n::BSInt, v pretend BArr] #(t: %): SingleInteger == rep(t).size::SingleInteger apply(t: %, i: SingleInteger):T == ArrElt(rep(t).values,(i-1)::BSInt) ++ Cross is the n-ary type cross product former. ++ Cross products may be cartesian or dependent. ++ Cross product values are not mutable. Cross(T: Tuple Type): with == add ++ Record is the n-ary record type former. ++ Records may be cartesian or dependent. ++ Record values are mutable. Record(T: Tuple Type): with == add ++ Union is the disjoint union type former. ++ Union values are not mutable. Union(T: Tuple Type): with == add ++ Enumeration forms a finite type consisting of given names. Enumeration(T: Tuple Type): with == add ++ Itertor(S) is a type which allows S values to be obtained serially ++ in a repeat or collect form. --!! The code generator uses a different representation today. --!! So the only valid function to call is "iterator". Iterator(S: Type): with IEnv ==> Record(place: BSInt, empty?: BBit, value: None) step!: % -> % ++ Run function, updating its environment. empty?: % -> Bit ++ This can be tested after calling "step!". value: % -> S ++ The value is valid if not "empty?". iterator: % -> % ++ Identity, allowing direct iteration. iterator: (IEnv -> None) -> % ++ Primitive constructor. == add Rep ==> Record(prog!: IEnv -> None, env: IEnv) IEnv ==> Record(place: BSInt, empty?: BBit, value: None) import Rep import IEnv --!! The two @ below should not be necessary. itprog(it) ==> rep(it).prog! @ IEnv->None itenv (it) ==> rep(it).env @ IEnv step! (it: %): % == (itprog(it) itenv(it); it) empty? (it: %): Bit == itenv(it).empty?::Bit value (it: %): S == itenv(it).value pretend S iterator(it: %): % == it iterator(prog!: IEnv -> None): % == per [prog!, [SInt0(), BitFalse(), SInt0()]] ++ Exit is a promise that the expression does not produce a result locally. ++ E.g. the expression "return x" has type Exit. ++ Exit /\ T => T Exit: with error: String -> % == add error(s: String): % == import Outport import Foreign: with fiHalt: BSInt -> % --!! print(s)() -- This give null syme. --!! Halt(0$BSInt) pretend % -- This give null syme. s pretend % ++ None is a type into which any value can be converted. ++ The original type information for the value is lost so the ++ only way to use a value of type None is to "pretend" it is of another type. ++ None /\ T => None None: with none: % == add Rep ==> BPtr none: % == per PtrNil() ++ Literal is the type in which the source literals are made available ++ to a progam. Literal: Type == add ++ Outport provides basic output. Outport: with print: % ++ Standard output. apply: % -> % ++ Put a newline. put: (%, Character) -> % put: (%, String) -> % -- These four are not primitive and will go away. put: (%, BSInt) -> % put: (%, BBInt) -> % put: (%, BSFlo) -> % put: (%, BDFlo) -> % == add Rep ==> BPtr import Foreign(): with printNewLine: () -> None printChar: Character -> None printString: String -> None printSInt: BSInt -> None printBInt: BBInt -> None printSFloat: BSFlo -> None printDFloat: BDFlo -> None print: % == per PtrNil() apply(p: %): % == (printNewLine(); p) put(p: %, c: Character): % == (printChar c; p) put(p: %, s: String): % == (printString s; p) put(p: %, i: BSInt): % == (printSInt i; p) put(p: %, i: BBInt): % == (printBInt i; p) put(p: %, x: BSFlo): % == (printSFloat x; p) put(p: %, x: BDFlo): % == (printDFloat x; p) ++ This data type supports logical operations. ++ Both arguments of the binary operations are always evaluated. Bit: with Object Finite Logic Conditional false: % true: % coerce: BBit -> % coerce: % -> BBit == add Rep ==> BBit (a: % = b: %): Bit == per BitEQ(rep a, rep b) (a: % ~= b: %): Bit == per BitNE(rep a, rep b) apply(p: Outport, b: %): Outport == put(p, BitToSInt rep b) min: % == per BitFalse() max: % == per BitTrue() (~ (a: %)): % == per BitNot(rep a) (a: % /\ b: %): % == per BitAnd(rep a,rep b) (a: % \/ b: %): % == per BitOr (rep a,rep b) test(b: %): Bit == rep b false: % == per BitFalse() true: % == per BitTrue() coerce(b: %): BBit == rep b coerce(b: BBit): % == per b ++ Single byte integers. Typically 8 bits. Byte: with Object Finite Logic OrderedArithmetic --!! Perhaps don't want * coerce: % -> BByte coerce: BByte -> % == add -- Missing lots of ops Rep ==> BByte 0: % == per Byte0() 1: % == per Byte1() min: % == per ByteMin() max: % == per ByteMax() apply(p: Outport, b: %): Outport == put(p, ByteToSInt rep b) coerce(b: %): BByte == rep b coerce(b: BByte): % == per b ++ Half-precision integers. Typically 16 bits. HalfInteger: with Object Finite Logic OrderedArithmetic coerce: % -> BHInt coerce: BHInt -> % == add -- Missing lots of ops Rep ==> BHInt 0: % == per HInt0() 1: % == per HInt1() min: % == per HIntMin() max: % == per HIntMax() apply(p: Outport, h: %): Outport == put(p, HIntToSInt rep h) coerce(h: %): BHInt == rep h coerce(h: BHInt): % == per h ++ Single-precision integers. Typically 32 bits. SingleInteger: with IntegerNumberSystem Finite Logic mod_+: (%,%,%)-> % mod_-: (%,%,%)-> % mod_*: (%,%,%)-> % mod_^: (%,%,%)-> % coerce: Bit -> % coerce: Byte -> % coerce: HalfInteger -> % coerce: % -> BSInt coerce: BSInt -> % == add Rep ==> BSInt import Bit 0: % == per SInt0() 1: % == per SInt1() min: % == per SIntMin() max: % == per SIntMax() integer(l:Literal): % == per ArrToSInt (l pretend BArr) zero? (i: %): Bit == SIntIsZero(rep i)::Bit negative?(i: %): Bit == SIntIsNeg (rep i)::Bit positive?(i: %): Bit == SIntIsPos (rep i)::Bit even? (i: %): Bit == SIntIsEven(rep i)::Bit odd? (i: %): Bit == SIntIsOdd (rep i)::Bit (i: % = j: %): Bit == SIntEQ (rep i, rep j)::Bit (i: % ~= j: %): Bit == SIntNE (rep i, rep j)::Bit (i: % > j: %): Bit == SIntGT (rep i, rep j)::Bit (i: % < j: %): Bit == SIntGT (rep j, rep i)::Bit (i: % >= j: %): Bit == SIntLE (rep j, rep i)::Bit (i: % <= j: %): Bit == SIntLE (rep i, rep j)::Bit abs(i: %): % == if i > 0 then i else -i dec(i: %): % == per SIntDec (rep i) inc(i: %): % == per SIntInc (rep i) (- i: %): % == per SIntNegate(rep i) (i: % + j: %): % == per SIntPlus (rep i, rep j) (i: % - j: %): % == per SIntMinus (rep i, rep j) (i: % * j: %): % == per SIntTimes (rep i, rep j) (i: % ^ j: %): % == per SIntPower (rep i, rep j) (i: % mod j: %): % == per SIntMod (rep i, rep j) (i: % quo j: %): % == per SIntQuo (rep i, rep j) (i: % rem j: %): % == per SIntRem (rep i, rep j) gcd(i: %, j: %): % == per SIntGcd (rep i, rep j) length(i:%): SingleInteger == (SIntLength rep i) pretend SingleInteger shift (i:%,n:SingleInteger): % == per SIntShift(rep i, n pretend BSInt) bit (i:%,n:SingleInteger): Bit == SIntBit(rep i, n pretend BSInt)::Bit (~ (i: %)) : % == per SIntNot(rep i) (i: % /\ j: %): % == per SIntAnd(rep i, rep j) (i: % \/ j: %): % == per SIntOr (rep i, rep j) mod_+(i:%, j:%, n:%): % == per SIntPlusMod (rep i,rep j,rep n) mod_-(i:%, j:%, n:%): % == per SIntMinusMod(rep i,rep j,rep n) mod_*(i:%, j:%, n:%): % == per SIntTimesMod(rep i,rep j,rep n) mod_^(i:%, j:%, n:%): % == j = 0 => 1 odd? j => mod_*(i, mod_^(i, j-1, n), n) mod_^(mod_*(i,i,n), j quo 2, n) -- divide(i: %, j: %): (%,%) == (i quo j, i rem j) divide!(i: %, j: %, r: Record(quo: %, rem: %)): None == SIntDivide(rep i, rep j, r pretend BRec) coerce(b: Bit): % == per BitToSInt (b::BBit) coerce(b: Byte): % == per ByteToSInt(b::BByte) coerce(h: HalfInteger): % == per HIntToSInt(h::BHInt) coerce(i: BSInt): % == per i coerce(i: %): BSInt == rep i retract(i: %): SingleInteger == i pretend SingleInteger apply(p: Outport, i: %): Outport == put(p, rep i) ++ Infinite precision integers. Integer: with IntegerNumberSystem coerce: SingleInteger -> % coerce: % -> BBInt coerce: BBInt -> % == add Rep ==> BBInt 0: % == per BInt0() 1: % == per BInt1() integer (l: Literal): % == per ArrToBInt (l pretend BArr) zero? (i: %): Bit == BIntIsZero (rep i)::Bit negative?(i: %): Bit == BIntIsNeg (rep i)::Bit positive?(i: %): Bit == BIntIsPos (rep i)::Bit even? (i: %): Bit == BIntIsEven (rep i)::Bit odd? (i: %): Bit == BIntIsOdd (rep i)::Bit single? (i: %): Bit == BIntIsSmall(rep i)::Bit (i: % = j: %): Bit == BIntEQ (rep i, rep j)::Bit (i: % ~= j: %): Bit == BIntNE (rep i, rep j)::Bit (i: % > j: %): Bit == BIntGT (rep i, rep j)::Bit (i: % < j: %): Bit == BIntGT (rep j, rep i)::Bit (i: % >= j: %): Bit == BIntLE (rep j, rep i)::Bit (i: % <= j: %): Bit == BIntLE (rep i, rep j)::Bit abs(i: %): % == if i > 0 then i else -i dec(i: %): % == per BIntDec (rep i) inc(i: %): % == per BIntInc (rep i) (- i: %): % == per BIntNegate (rep i) (i: % + j: %): % == per BIntPlus (rep i, rep j) (i: % - j: %): % == per BIntMinus (rep i, rep j) (i: % * j: %): % == per BIntTimes (rep i, rep j) (i: % ^ j: %): % == per BIntPower (rep i, rep j) (i: % mod j: %): % == per BIntMod (rep i, rep j) (i: % quo j: %): % == per BIntQuo (rep i, rep j) (i: % rem j: %): % == per BIntRem (rep i, rep j) gcd(i: %, j: %): % == per BIntGcd (rep i, rep j) length(i:%): SingleInteger == BIntLength(rep i)::SingleInteger shift (i:%,n:SingleInteger):% == per BIntShift (rep i, n::BSInt) bit (i:%,n:SingleInteger):Bit == BIntBit (rep i, n::BSInt)::Bit -- divide(i: %, j: %): (%,%) == -- r: Record(quo: %, rem: %) := [0, 0] -- divide!(i, j, r) -- (r.quo, r.rem) divide!(i: %, j: %, r: Record(quo: %, rem: %)): None == BIntDivide(rep i, rep j, r pretend BRec) apply(p: Outport, i: %): Outport == put(p, rep i) coerce (i: SingleInteger): % == per SIntToBInt(i::BSInt) retract(i: %): SingleInteger == (BIntToSInt rep i)::SingleInteger coerce(i: %): BBInt == rep i coerce(i: BBInt): % == per i ++ Single-precision floating point numbers. ++ ++ In the portable byte code files, single precision floats are represented ++ in IEEE single precision format. (This will later be extended single prec.) ++ In a running program, single precision floats are represented according ++ to the machine's native arithmetic. SingleFloat: with FiniteFloatingPointNumberSystem coerce: BSFlo -> % coerce: % -> BSFlo == add Rep ==> BSFlo 0: % == per SFlo0() 1: % == per SFlo1() min: % == per SFloMin() max: % == per SFloMax() epsilon: % == per SFloEpsilon() float(l: Literal): % == per ArrToSFlo(l pretend BArr) zero? (x: %): Bit == SFloIsZero(rep x)::Bit negative?(x: %): Bit == SFloIsNeg (rep x)::Bit positive?(x: %): Bit == SFloIsPos (rep x)::Bit (x: % = y: %): Bit == SFloEQ (rep x, rep y)::Bit (x: % ~= y: %): Bit == SFloNE (rep x, rep y)::Bit (x: % > y: %): Bit == SFloGT (rep x, rep y)::Bit (x: % < y: %): Bit == SFloGT (rep y, rep x)::Bit (x: % >= y: %): Bit == SFloLE (rep y, rep x)::Bit (x: % <= y: %): Bit == SFloLE (rep x, rep y)::Bit abs(x:%): % == if x > 0 then x else -x (- x:%): % == per SFloNegate(rep x) (x: % + y: %): % == per SFloPlus (rep x, rep y) (x: % - y: %): % == per SFloMinus (rep x, rep y) (x: % * y: %): % == per SFloTimes (rep x, rep y) (x: % / y: %): % == per SFloDivide(rep x, rep y) (x: % ^ y: %): % == per SFloPower (rep x, rep y) (x: % ^ n: Integer): % == per SFloIPower(rep x, n::BBInt) round (x: %): Integer == SFloRound rep x::Integer truncate(x: %): Integer == SFloTruncate rep x::Integer floor (x: %): Integer == SFloFloor rep x::Integer ceiling (x: %): Integer == SFloCeiling rep x::Integer apply(p: Outport, x: %): Outport == put(p, rep x) step(n:SingleInteger)(a:%, b:%): Iterator % == iterate import Segment SingleInteger del := (b - a)/(n - 1)::% for i in 1..n repeat yield a a := a + del coerce(n: Integer): % == per BIntToSFlo(n::BBInt) coerce(n: SingleInteger): % == per SIntToSFlo(n::BSInt) coerce(x: BSFlo): % == per x coerce(x: %): BSFlo == rep x ++ Double-precision floating point numbers. ++ ++ In the portable byte code files, double precision floats are represented ++ in IEEE double precision format. (This will later be exended dbl prec.) ++ In a running program, double precision floats are represented according ++ to the machine's native arithmetic. DoubleFloat: with FiniteFloatingPointNumberSystem coerce: BDFlo -> % coerce: % -> BDFlo == add Rep ==> Record(double: BDFlo) --!! Temporarily box by hand. import Rep box(b) ==> per [b] raw(f) ==> rep(f).double 0: % == box DFlo0() 1: % == box DFlo1() min: % == box DFloMin() max: % == box DFloMax() epsilon: % == box DFloEpsilon() float(l: Literal): % == box ArrToDFlo(l pretend BArr) zero? (x: %): Bit == DFloIsZero(raw x)::Bit negative?(x: %): Bit == DFloIsNeg (raw x)::Bit positive?(x: %): Bit == DFloIsPos (raw x)::Bit (x: % = y: %): Bit == DFloEQ (raw x, raw y)::Bit (x: % ~= y: %): Bit == DFloNE (raw x, raw y)::Bit (x: % > y: %): Bit == DFloGT (raw x, raw y)::Bit (x: % < y: %): Bit == DFloGT (raw y, raw x)::Bit (x: % >= y: %): Bit == DFloLE (raw y, raw x)::Bit (x: % <= y: %): Bit == DFloLE (raw x, raw y)::Bit abs(x:%): % == if x > 0 then x else -x (- x:%): % == box DFloNegate(raw x) (x: % + y: %): % == box DFloPlus (raw x, raw y) (x: % - y: %): % == box DFloMinus (raw x, raw y) (x: % * y: %): % == box DFloTimes (raw x, raw y) (x: % / y: %): % == box DFloDivide(raw x, raw y) (x: % ^ y: %): % == box DFloPower (raw x, raw y) (x: % ^ n: Integer): % == box DFloIPower(raw x, n::BBInt) round (x: %): Integer == DFloRound raw x::Integer truncate(x: %): Integer == DFloTruncate raw x::Integer floor (x: %): Integer == DFloFloor raw x::Integer ceiling (x: %): Integer == DFloCeiling raw x::Integer apply(p: Outport, x: %): Outport == put(p, raw x) step(n:SingleInteger)(a:%, b:%): Iterator % == iterate import Segment SingleInteger del := (b - a)/(n - 1)::% for i in 1..n repeat yield a a := a + del coerce(n: Integer): % == box BIntToDFlo(n::BBInt) coerce(n: SingleInteger): % == box SIntToDFlo(n::BSInt) coerce(x: BDFlo): % == box x coerce(x: %): BDFlo == raw x ++ Characters for natural language text. ++ ++ In the portable byte code files, characters are represented in ASCII. ++ In a running program, characters are represented according to the ++ machine's native character set, e.g. ASCII or EBCDIC. Character: with Object Ordered Finite space: % newline: % digit?: % -> Bit letter?: % -> Bit lower: % -> % upper: % -> % ord: % -> SingleInteger char: SingleInteger -> % coerce: % -> BChar coerce: BChar -> % == add Rep ==> BChar space: % == per CharSpace() newline: % == per CharNewline() min: % == per CharMin() max: % == per CharMax() digit? (c: %): Bit == CharIsDigit (rep c)::Bit letter?(c: %): Bit == CharIsLetter(rep c)::Bit (a: % = b: %): Bit == CharEQ(rep a, rep b)::Bit (a: % ~= b: %): Bit == CharNE(rep a, rep b)::Bit (a: % > b: %): Bit == CharGT(rep a, rep b)::Bit (a: % < b: %): Bit == CharGT(rep b, rep a)::Bit (a: % >= b: %): Bit == CharLE(rep b, rep a)::Bit (a: % <= b: %): Bit == CharLE(rep a, rep b)::Bit lower(c: %): % == per CharLower rep c upper(c: %): % == per CharUpper rep c ord(c: %): SingleInteger == CharOrd(rep c)::SingleInteger char(i: SingleInteger):% == per CharNum(i::BSInt) apply(p: Outport, c: %): Outport == put(p, c pretend Character) coerce(c: BChar): % == per c coerce(c: %): BChar == rep c ++ Pointers to opaque objects. Pointer: with Object nil: % nil?: % -> Bit coerce: BPtr -> % coerce: % -> BPtr == add Rep ==> BPtr nil: % == per PtrNil() nil?(p: %): Bit == PtrIsNil (rep p)::Bit (p: % = q: %): Bit == PtrEQ (rep p, rep q)::Bit apply(p: Outport, q: %): Outport == put(p, PtrToSInt rep q) coerce(p: BPtr): % == per p coerce(p: %): BPtr == rep p ++ Segment(S) provides ranges for indexing or iteration. Segment(S: with(OrderedArithmetic; *: (%,%)->%) ): with ..: (S) -> % ..: (S, S) -> % by: (%, S) -> % open?: % -> Bit low: % -> S high: % -> S step: % -> S iterator: % -> Iterator S == add Rep ==> Record(open?: Bit, low: S, high: S, step: S) import S import Bit import Rep (a:S .. ):% == per [true, a, 0, 1] (a:S .. b:S):% == per [false, a, b, 1] (s:% by d:S):% == per [open? s, low s, high s, d * step s] open?(s: %): Bit == rep(s).open? low (s: %): S == rep(s).low high (s: %): S == rep(s).high step (s: %): S == rep(s).step iterator(s: %): Iterator S == iterate a := low s b := high s d := step s open? s => repeat (yield a; a := a + d) d >= 0 => while a <= b repeat (yield a; a := a + d) d < 0 => while a >= b repeat (yield a; a := a + d) ++ Character strings for natural language text. String: with StrPos ==> Record(index: SingleInteger) Object string: Literal -> % new: (SingleInteger, Character) -> % new: SingleInteger -> % copy: % -> % #: % -> SingleInteger apply: (%, SingleInteger) -> Character apply: (%, Segment SingleInteger) -> % set!: (%, SingleInteger, Character) -> Character fill!: (%, Segment SingleInteger, Character) -> % -- concat: Tuple(%) -> % concat: (%, %) -> % concat: (%, %, %) -> % concat: (%, %, %, %) -> % replace!: (%, SingleInteger, %) -> SingleInteger ++ replace!(s1, ind, s2) replaces characters in s1 ++ begining at position ind with characters from s2. ++ Returns the next available position in s1. substring: (%, SingleInteger, SingleInteger) -> % ++ substring(s, start, len) returns the substring of s ++ from position start of length len. rightTrim: (%, Character) -> % ++ rightTrim(s,c) removes trailing occurrences of c from s. leftTrim: (%, Character) -> % ++ leftTrim(s,c) removes leading occurrences of c from s. map: (f: Character -> Character, %) -> % map!: (f: Character -> Character, %) -> % iterator: % -> Iterator Character format: (SingleFloat, %, StrPos) -> SingleInteger format: (DoubleFloat, %, StrPos) -> SingleInteger format: (SingleInteger, %, StrPos) -> SingleInteger format: (Integer, %, StrPos) -> SingleInteger scan: (%, StrPos) -> SingleFloat scan: (%, StrPos) -> DoubleFloat scan: (%, StrPos) -> SingleInteger scan: (%, StrPos) -> Integer == add StrPos ==> Record(index: SingleInteger) Rep ==> BArr import Bit import Character import SingleInteger import Segment SingleInteger import Builtin: with ArrNew: (BChar, BSInt) -> BArr ArrElt: (BArr, BSInt) -> BChar ArrSet: (BArr, BSInt, BChar) -> BChar ---- Representation ---- EOS := 0 pretend Character --!! char 0 -- instantiation order empty(size: SingleInteger): % == s := per ArrNew(EOS::BChar, (size+1)::BSInt) ArrSet(rep s, 0::BSInt, EOS::BChar) ArrSet(rep s, size::BSInt, EOS::BChar) s apply(s: %, i: SingleInteger): Character == ArrElt(rep s, (i-1)::BSInt)::Character set!(s: %, i: SingleInteger, c: Character): Character == ArrSet(rep s, (i-1)::BSInt, c::BChar)::Character ---- String operations ---- new(size: SingleInteger, c: Character): % == s := empty size for i in 1..size repeat s.i := c s new(size: SingleInteger): % == new(size, space) copy(s: %): % == len := #s r := empty len for i in 1..len repeat r.i := s.i r #(s: %): SingleInteger == for i in 1.. repeat s.i = EOS => return (i-1) never (s1: % = s2: %): Bit == for i in 1.. repeat c := s1.i c = EOS => return s2.i = c c ~= s2.i => return false true (s1: % ~= s2: %): Bit == ~(s1 = s2) replace!(s1: %, pos: SingleInteger, sub: %): SingleInteger == for i in 1.. for ii in pos.. repeat c := sub.i c = EOS or s1.ii = EOS => return ii s1.ii := c never substring(s1: %, pos: SingleInteger, len: SingleInteger): % == s2 := empty len for i in 1..len for j in pos.. repeat s2.i := s1.j s2 apply(s: %, seg: Segment SingleInteger): % == pos := low seg len := (if open? seg then #s else high seg) - pos + 1 substring(s, pos, len) fill!(s: %, seg: Segment SingleInteger, c: Character): % == len := #s for i in seg while i <= len repeat s.i := c s concat(s1: %, s2: %): % == s1.1 = EOS => s2 s3 := new(#s1 + #s2) replace!(s3,replace!(s3,1,s1),s2) s3 concat(s1: %, s2: %, s3: %): % == s4 := new(#s1 + #s2 + #s3) replace!(s4,replace!(s4,replace!(s4,1,s1),s2),s3) s4 concat(s1: %, s2: %, s3: %, s4: %): % == s5 := new(#s1 + #s2 + #s3 + #s4) replace!(s5,replace!(s5,replace!(s5,replace!(s5,1,s1),s2),s3),s4) s5 rightTrim(s: %, c: Character): % == len := #s for i in len..1 by -1 repeat s.i ~= c => return substring(s, 1, i) empty 0 leftTrim(s: %, c: Character): % == len := #s for i in 1..len repeat s.i ~= c => return substring(s, i, len-i+1) empty 0 map!(f: Character -> Character, s: %): % == for i in 1.. repeat c := s.i c = EOS => return s s.i := f c s map(f: Character -> Character, s: %): % == s2 := empty(l := #s) for i in 1..l repeat s2.i := f s.i s2 iterator(s: %): Iterator Character == iterate for i in 1.. while (c := s.i) ~= EOS repeat yield c string(l: Literal): % == l pretend % apply(p: Outport, s: %): Outport == put(p, s pretend String) ---- Scanning and formatting operations (to go) ---- macro ptr x == x pretend BRec format(x: SingleFloat, s: %,r: StrPos): SingleInteger == FormatSFlo(x::BSFlo,rep s,ptr r)::SingleInteger format(x: DoubleFloat, s: %,r: StrPos): SingleInteger == FormatDFlo(x::BDFlo,rep s,ptr r)::SingleInteger format(i: SingleInteger,s: %,r: StrPos): SingleInteger == FormatSInt(i::BSInt,rep s,ptr r)::SingleInteger format(i: Integer, s: %,r: StrPos): SingleInteger == FormatBInt(i::BBInt,rep s,ptr r)::SingleInteger scan(s: %, r: StrPos): SingleFloat == ScanSFlo(rep s, ptr r)::SingleFloat scan(s: %, r: StrPos): DoubleFloat == ScanDFlo(rep s, ptr r)::DoubleFloat scan(s: %, r: StrPos): SingleInteger == ScanSInt(rep s, ptr r)::SingleInteger scan(s: %, r: StrPos): Integer == ScanBInt(rep s, ptr r)::Integer