home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
src
/
runtime
/
fconv.r
< prev
next >
Wrap
Text File
|
2002-01-18
|
5KB
|
261 lines
/*
* fconv.r -- abs, cset, integer, numeric, proc, real, string.
*/
"abs(N) - produces the absolute value of N."
function{1} abs(n)
/*
* If n is convertible to a (large or small) integer or real,
* this code returns -n if n is negative
*/
if cnv:(exact)C_integer(n) then {
abstract {
return integer
}
inline {
C_integer i;
extern int over_flow;
if (n >= 0)
i = n;
else {
i = neg(n);
if (over_flow) {
#ifdef LargeInts
struct descrip tmp;
MakeInt(n,&tmp);
if (bigneg(&tmp, &result) == Error) /* alcbignum failed */
runerr(0);
return result;
#else /* LargeInts */
irunerr(203,n);
errorfail;
#endif /* LargeInts */
}
}
return C_integer i;
}
}
#ifdef LargeInts
else if cnv:(exact)integer(n) then {
abstract {
return integer
}
inline {
if (BlkLoc(n)->bignumblk.sign == 0)
result = n;
else {
if (bigneg(&n, &result) == Error) /* alcbignum failed */
runerr(0);
}
return result;
}
}
#endif /* LargeInts */
else if cnv:C_double(n) then {
abstract {
return real
}
inline {
return C_double Abs(n);
}
}
else
runerr(102,n)
end
/*
* The convertible types cset, integer, real, and string are identical
* enough to be expansions of a single macro, parameterized by type.
*/
#begdef ReturnYourselfAs(t)
#t "(x) - produces a value of type " #t " resulting from the conversion of x, "
"but fails if the conversion is not possible."
function{0,1} t(x)
if cnv:t(x) then {
abstract {
return t
}
inline {
return x;
}
}
else {
abstract {
return empty_type
}
inline {
fail;
}
}
end
#enddef
ReturnYourselfAs(cset) /* cset(x) - convert to cset or fail */
ReturnYourselfAs(integer) /* integer(x) - convert to integer or fail */
ReturnYourselfAs(real) /* real(x) - convert to real or fail */
ReturnYourselfAs(string) /* string(x) - convert to string or fail */
"numeric(x) - produces an integer or real number resulting from the "
"type conversion of x, but fails if the conversion is not possible."
function{0,1} numeric(n)
if cnv:(exact)integer(n) then {
abstract {
return integer
}
inline {
return n;
}
}
else if cnv:real(n) then {
abstract {
return real
}
inline {
return n;
}
}
else {
abstract {
return empty_type
}
inline {
fail;
}
}
end
"proc(x,i) - convert x to a procedure if possible; use i to resolve "
"ambiguous string names."
#ifdef MultiThread
function{0,1} proc(x,i,c)
#else /* MultiThread */
function{0,1} proc(x,i)
#endif /* MultiThread */
#ifdef MultiThread
if is:coexpr(x) then {
abstract {
return proc
}
inline {
struct b_coexpr *ce = NULL;
struct b_proc *bp = NULL;
struct pf_marker *fp;
dptr dp=NULL;
if (BlkLoc(x) != BlkLoc(k_current)) {
ce = (struct b_coexpr *)BlkLoc(x);
dp = ce->es_argp;
if (dp == NULL) fail;
bp = (struct b_proc *)BlkLoc(*(dp));
}
else
bp = (struct b_proc *)BlkLoc(*(glbl_argp));
return proc(bp);
}
}
#endif /* MultiThread */
if is:proc(x) then {
abstract {
return proc
}
inline {
#ifdef MultiThread
if (!is:null(c)) {
struct progstate *p;
if (!is:coexpr(c)) runerr(118,c);
/*
* Test to see whether a given procedure belongs to a given
* program. Currently this is a sleazy pointer arithmetic check.
*/
p = BlkLoc(c)->coexpr.program;
if (! InRange(p, BlkLoc(x)->proc.entryp.icode,
(char *)p + p->hsize))
fail;
}
#endif /* MultiThread */
return x;
}
}
else if cnv:tmp_string(x) then {
/*
* i must be 0, 1, 2, or 3; it defaults to 1.
*/
if !def:C_integer(i, 1) then
runerr(101, i)
inline {
if (i < 0 || i > 3) {
irunerr(205, i);
errorfail;
}
}
abstract {
return proc
}
inline {
struct b_proc *prc;
#ifdef MultiThread
struct progstate *prog, *savedprog;
savedprog = curpstate;
if (is:null(c)) {
prog = curpstate;
}
else if (is:coexpr(c)) {
prog = BlkLoc(c)->coexpr.program;
}
else {
runerr(118,c);
}
ENTERPSTATE(prog);
#endif /* MultiThread */
/*
* Attempt to convert Arg0 to a procedure descriptor using i to
* discriminate between procedures with the same names. If i
* is zero, only check builtins and ignore user procedures.
* Fail if the conversion isn't successful.
*/
if (i == 0)
prc = bi_strprc(&x, 0);
else
prc = strprc(&x, i);
#ifdef MultiThread
ENTERPSTATE(savedprog);
#endif /* MultiThread */
if (prc == NULL)
fail;
else
return proc(prc);
}
}
else {
abstract {
return empty_type
}
inline {
fail;
}
}
end