5 * Created by Alyssa Milburn on Tue May 25 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
35 #include "shared_str.h"
42 unsigned short lineno
;
44 toktrace(unsigned short w
, unsigned short l
) : width(w
), lineno(l
) { }
46 FRIEND_SERIALIZE(toktrace
);
52 FRIEND_SERIALIZE(script
);
56 // position 0 is reserved in the below vector
57 // relocations[-relocid] is the target address for relocation relocid
58 // will be 0 if unresolved
59 std::vector
<int> relocations
;
60 // map of name -> (address|relocation)
61 std::map
<std::string
, int> labels
;
64 // ops[0] is initted to a nop, as address 0 is reserved for a flag value
65 // in the relocation vector
66 std::vector
<caosOp
> ops
;
67 // table of all non-trivial constants in the script
68 // small immediates integers are done with CAOS_CONSTINT
69 // mostly for strings and floats
70 std::vector
<caosVar
> consts
;
71 // because caosVar doesn't store bytestrings, we store them in a separate
73 std::vector
<bytestring_t
> bytestrs
;
74 // a normalized copy of the script source. this is used for error tracing
76 shared_ptr
<std::vector
<toktrace
> > tokinfo
;
79 int fmly
, gnus
, spcs
, scrp
;
80 const class Dialect
*dialect
;
81 const Dialect
*getDialect() const { return dialect
; };
85 caosOp
getOp(int idx
) const {
87 return (size_t)idx
>= ops
.size() ? caosOp(CAOS_DIE
, -1, -1) : ops
[idx
];
90 int scriptLength() const {
94 caosVar
getConstant(int idx
) const {
95 if (idx
< 0 || (size_t)idx
>= consts
.size()) {
96 throw caosException(boost::str(
97 boost::format("Internal error: const %d out of range") % idx
103 bytestring_t
getBytestr(int idx
) const {
104 if (idx
< 0 || (size_t)idx
>= bytestrs
.size()) {
105 throw caosException(boost::str(
106 boost::format("Internal error: const %d out of range") % idx
109 return bytestrs
[idx
];
112 std::map
<std::string
, int> gsub
;
113 int getNextIndex() { return ops
.size(); }
114 // add op as the next opcode
115 script(const Dialect
*v
, const std::string
&fn
,
116 int fmly_
, int gnus_
, int spcs_
, int scrp_
);
117 script(const Dialect
*v
, const std::string
&fn
);
120 // std::string dumpLine(unsigned int);
124 int newRelocation() {
126 int idx
= relocations
.size();
127 relocations
.push_back(0);
131 void fixRelocation(int r
, int p
) {
135 assert (relocations
[r
] == 0);
141 throw creaturesException("relocation loop found");
148 // fix relocation r to point to the next op to be emitted
149 void fixRelocation(int r
) {
150 fixRelocation(r
, getNextIndex());
153 // find the address of the given label, could be a relocation
154 int getLabel(const std::string
&label
) {
155 if (labels
.find(label
) == labels
.end())
156 labels
[label
] = newRelocation();
157 return labels
[label
];
160 // fix a label to the end of the current op string
161 void affixLabel(const std::string
&label
) {
162 int reloc
= getLabel(label
);
164 throw caosException(std::string("Label ") + label
+ " redefined");
165 fixRelocation(reloc
);
166 labels
[label
] = getNextIndex();
169 void emitOp(opcode_t op
, int argument
);
177 class CAOSExpression
;
181 std::vector
<boost::shared_ptr
<CAOSExpression
> > arguments
;
183 CAOSCmd() { op
= 0; traceidx
= -1; }
184 CAOSCmd(const CAOSCmd
&c
) : op(c
.op
), arguments(c
.arguments
) { }
187 struct CAOSExpression
{
188 boost::variant
<CAOSCmd
, caosVar
, bytestring_t
> value
;
190 void eval(caosScript
*scr
, bool save_here
) const;
191 void save(caosScript
*scr
) const;
194 CAOSExpression(const CAOSExpression
&e
) : value(e
.value
), traceidx(e
.traceidx
) { }
195 CAOSExpression(int idx
, const CAOSCmd
&c
) : value(c
), traceidx(idx
) { boost::get
<CAOSCmd
>(value
).traceidx
= traceidx
; }
196 CAOSExpression(int idx
, const caosVar
&c
) : value(c
), traceidx(idx
) { }
197 CAOSExpression(int idx
, const bytestring_t
&c
) : value(c
), traceidx(idx
) { }
202 struct costVisit
: public boost::static_visitor
<int> {
205 int operator()(const CAOSCmd
&cmd
) const;
207 int operator()(const caosVar
&v
) const { (void)v
; return 0; }
208 int operator()(const bytestring_t
&v
) const { (void)v
;return 0; }
211 struct saveVisit
: public boost::static_visitor
<void> {
215 saveVisit(class caosScript
*s
);
216 void operator()(const CAOSCmd
&cmd
) const;
218 void operator()(const caosVar
&v
) const { (void)v
; }
219 void operator()(const bytestring_t
&v
) const { (void)v
; }
222 struct evalVisit
: public boost::static_visitor
<void> {
227 evalVisit(caosScript
*s
, bool save_here
);
228 void operator()(const CAOSCmd
&cmd
) const;
229 void operator()(const caosVar
&v
) const;
230 void operator()(const bytestring_t
&bs
) const;
233 class caosScript
{ //: Collectable {
236 std::string filename
;
237 shared_ptr
<script
> installer
, removal
;
238 std::vector
<shared_ptr
<script
> > scripts
;
239 shared_ptr
<script
> current
;
241 caosScript(const std::string
&dialect
, const std::string
&fn
);
242 caosScript() { d
= NULL
; }
243 void parse(std::istream
&in
);
245 void installScripts();
246 void installInstallScript(unsigned char family
, unsigned char genus
, unsigned short species
, unsigned short eventid
);
249 void parseCondition();
250 void emitOp(opcode_t op
, int argument
);
251 void emitCmd(const char *name
);
252 boost::shared_ptr
<CAOSExpression
> readExpr(const enum ci_type xtype
);
253 void emitExpr(boost::shared_ptr
<CAOSExpression
> ce
);
254 const cmdinfo
*readCommand(class token
*t
, const std::string
&prefix
);
255 void parseloop(int state
, void *info
);
257 shared_ptr
<std::vector
<token
> > tokens
;
258 int curindex
; // index to the next token to be read
259 int errindex
; // index to the token to report parse errors on
260 int traceindex
; // index to the token to report runtime errors on
262 // deprecated support functions
264 void putBackToken(token
*);
265 token
*getToken(toktype expected
= ANYTOKEN
);
267 friend struct saveVisit
;
268 friend struct evalVisit
;