summaryrefslogtreecommitdiff
path: root/functions.m
blob: ef3e6c3ce7910c62e36f1c1fd284638092118116 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* -*- mode: objc; coding: utf-8 -*- */
/* Étoilisp/Mulklisp, a Common Lisp subset for the Étoilé runtime.
 * Copyright (C) 2008  Matthias Andreas Benkard.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#import "functions.h"
#import "MLKInteger.h"

NSString *MLKPrintToString (id object)
{
  if (object == nil)
    return @"()";
  else if (MLKInstanceP (object))
    return [object descriptionForLisp];
  else if (MLKFixnumP (object))
    return MLKPrintToString ([MLKInteger
                               integerWithIntptr_t:(MLKIntWithFixnum (object))]);
  else
    {
      NSLog (@"MLKPrintToString: Encountered a really weird object at address %p",
             object);
      return @"<??\?>";
    }
}

intptr_t MLKIntWithFixnum (id fixnum)
{
  return ((intptr_t)fixnum >> 1);
}

id MLKFixnumWithInt (intptr_t value)
{
  return (id)((value << 1) | 1);
}

id MLKIntegerWithInt (intptr_t value)
{
#ifndef NO_FIXNUMS
  intptr_t maybeFixnum = (value << 1) | 1;
  if (value == (maybeFixnum >> 1))
    return (id)maybeFixnum;
  else
#endif
    return [MLKInteger integerWithIntptr_t:value];
}

BOOL MLKFixnumP (id thing)
{
  return ((intptr_t)thing & 1);
}

BOOL MLKInstanceP (id thing)
{
  return !((intptr_t)thing & 1);
}

id MLKCanoniseInteger (MLKInteger *x)
{
  if (MLKFixnumP (x))
    {
      return x;
    }
  else if (MLKInstanceP (x))
    {
      if ([x fitsIntoFixnum])
        return [x fixnumValue];
      else
        return x;
    }
  else
    {
      NSLog (@"MLKCanoniseInteger: Encountered a really weird object at address %p",
             x);
      return 0;
    }
}

id MLKAddFixnums (id x, id y)
{
  intptr_t ix = MLKIntWithFixnum (x);
  intptr_t iy = MLKIntWithFixnum (y);
  intptr_t result = ix + iy;

  return MLKIntegerWithInt (result);
}

id MLKSubtractFixnums (id x, id y)
{
  intptr_t ix = MLKIntWithFixnum (x);
  intptr_t iy = MLKIntWithFixnum (y);
  intptr_t result = ix - iy;

  return MLKIntegerWithInt (result);
}

id MLKIDivideFixnums (id x, id y)
{
  intptr_t ix = MLKIntWithFixnum (x);
  intptr_t iy = MLKIntWithFixnum (y);
  intptr_t result = ix / iy;

  return MLKIntegerWithInt (result);
}

id MLKMultiplyFixnums (id x, id y)
{
  id ix = [MLKInteger integerWithFixnum:x];
  id iy = [MLKInteger integerWithFixnum:y];
  id result = [ix multiplyWith:iy];

  return MLKCanoniseInteger (result);
}