rustlr/generic_absyn.rs
1//! Generic Abstract Syntax Support Module
2//!
3//! Rustlr allows any type that implements the Default trait to be used as
4//! the abstract syntax type (grammar directive absyntype). However, this
5//! module defines custom smart pointers [LBox] and [LRc] that simplify the
6//! construction of abstract syntax trees. LBox/LRc keep the line and column
7//! numbers of each syntatic construct, as these are often
8//! needed during later stages of code analysis post-parsing.
9//!
10//! For example, an abstract syntax type can be defined by
11//!```text
12//! enum Expr {
13//! Val(i64),
14//! PlusExpr(LBox<Expr>,LBox<Expr>),
15//! ...
16//! }
17//!```
18//!```text
19//! fn check(e:&Expr) {
20//! match e {
21//! PlusExpr(a,b) => {
22//! println!("checking expressions on lines {} and {}",a.line(),b.line());
23//! check(a); check(b); // Deref coercion used here
24//! },
25//! ...
26//!```
27//! The [ZCParser::lbx] function can be called from the semantic actions
28//! of a grammar
29//! to create LBoxed-values that include line/column information. `LBox<T>`
30//! implements the Default trait if T does, so an LBox type can also serve
31//! as the absyntract syntax type for a grammar.
32//! It is also possible to use `LBox<dyn Any>` as the abstract syntax type
33//! along with the [LBox::upcast] and [LBox::downcast] functions and
34//! convenience macros [lbup] and [lbdown].
35//!
36//! Sufficient functionality has also been implemented to allow the use of
37//! `LBox<dyn Any>` as the abstract syntax type of Grammars.
38//! This effectively allows grammar symbols to carray values of different types
39//! as Any-trait objects. The functions [LBox::upcast], [LBox::downcast], [ZCParser::lba],
40//! and the convenience macros [lbup], [lbdown] and [lbget]
41//! are intended to support this usage. A simplified, sample grammar using
42//! `LBox<dyn Any>` as the abstract syntax type returned by the parser is
43//! found [here](https://cs.hofstra.edu/~cscccl/rustlr_project/simple.grammar),
44//! which generates this LALR [parser](https://cs.hofstra.edu/~cscccl/rustlr_project/simpleparser.rs).
45//!
46//! Equivalent functions are available for [LRc].
47
48#![allow(dead_code)]
49#![allow(unused_variables)]
50#![allow(unused_parens)]
51#![allow(unused_imports)]
52#![allow(unused_mut)]
53#![allow(unused_macros)]
54#![allow(non_snake_case)]
55#![allow(non_camel_case_types)]
56#![allow(non_upper_case_globals)]
57
58use std::rc::Rc;
59use std::ops::{Deref,DerefMut};
60use std::collections::{HashMap,HashSet};
61use std::any::Any;
62use crate::zc_parser;
63use crate::zc_parser::ZCParser;
64use crate::{lbup,lbdown,lbget};
65use bumpalo::Bump;
66
67/// Custom smart pointer that encapsulates line and column numbers along with
68/// a regular [Box]. Implements [Deref] and [DerefMut] so the encapsulated
69/// expression can be accessed as in a standard Box. This is intended to
70/// to be used in the formation of abstract syntax trees so that the lexical
71/// information is available for each construct after the parsing stage.
72/// Also included in each LBox created by the runtime parser ([ZCParser])
73/// is a 32 bit (u32) *unique identifier* **uid** that uniquely identifies
74/// each LBox. An expression and a subexpression can both begin at the same
75/// line and column numbers and the unique id would be required to
76/// distinguish them. This device is useful for hashing information, such
77/// as inferred types, based on the location of an expression in the source.
78pub struct LBox<T:?Sized>
79{
80 pub exp:Box<T>,
81 pub line:u32,
82 pub column:u32,
83 pub uid:u32, // unique id
84 // must refer to information kept externally
85 //pub src_id:usize,
86}
87impl<T> LBox<T>
88{
89 /// creates a new LBox with line ln, column col and uid set to zero;
90 /// this function is deprecated by [LBox::make].
91 pub fn new(e:T,ln:usize,col:usize /*,src:usize*/) -> LBox<T>
92 { LBox { exp:Box::new(e), line:ln as u32, column:col as u32,uid:0, } }
93 /// creates a new LBox enclosing e, with line ln, column col and uid u
94 pub fn make(e:T,ln:usize,col:usize, u:u32) -> LBox<T>
95 { LBox { exp:Box::new(e), line:ln as u32, column:col as u32,uid:u, } }
96 ///should be used to create a new LBoxed expression that inherits
97 /// lexical information from existing LBox
98 pub fn transfer<U>(&self,e:U) -> LBox<U>
99 {
100 LBox::make(e,self.line(),self.column(),self.uid)
101 }
102 /// Since version 0.2.4, Rustlr now stores the line and column
103 /// information internally as u32 values instead of usize, and
104 /// the [LBox::line] and [LBox::column] functions are provided for
105 /// interface
106 pub fn line(&self)-> usize {self.line as usize}
107 pub fn column(&self)->usize {self.column as usize}
108 pub fn uid(&self) -> u32 {self.uid}
109}//impl LBox
110impl<T> Deref for LBox<T>
111{
112 type Target = T;
113 fn deref(&self) -> &Self::Target {
114 &self.exp
115 }
116}
117impl<T> DerefMut for LBox<T>
118{
119 fn deref_mut(&mut self) -> &mut Self::Target {
120 &mut self.exp
121 }
122}
123impl<T:Default> Default for LBox<T>
124{
125 fn default() -> Self {LBox::new(T::default(),0,0/*,0*/)}
126}
127impl<T:Clone> Clone for LBox<T>
128{
129 fn clone(&self) -> Self
130 {
131 LBox {
132 exp : self.exp.clone(),
133 line: self.line,
134 column: self.column,
135 uid:self.uid,
136 //src_id: self.src_id,
137 }
138 }//clone
139}
140impl<T:?Sized> AsRef<T> for LBox<T>
141{
142 fn as_ref(&self) -> &T { &*self.exp }
143}
144impl<T:?Sized> AsMut<T> for LBox<T>
145{
146 fn as_mut(&mut self) -> &mut T { &mut *self.exp }
147}
148impl<T:Default+?Sized> LBox<T>
149{
150 /// replaces the boxed value with T::default() and returns the value
151 pub fn take(&mut self) -> T
152 { let mut res = T::default();
153 std::mem::swap(&mut res, self.as_mut());
154 res
155 }
156 /// convert information from [LC] to LBox, consumes LC
157 pub fn from_lc(c:LC<T>) -> Self
158 {
159 LBox{exp:Box::new(c.0), line:c.1.0, column:c.1.1, uid:c.1.2}
160 }
161}
162impl<'t> LBox<dyn Any+'t>
163{
164 /// emulates [Box::downcast] function, when `LBox<dyn Any>` is used as
165 /// the abstract syntax type. Note that unlike Box::downcast, an Option
166 /// is returned here instead of a result.
167 pub fn downcast<U:'t>(self) -> Option<LBox<U>>
168 {
169 let boxdown = self.exp.downcast::<U>();
170 if let Err(_) = boxdown {return None;}
171 Some(LBox {
172 exp : boxdown.unwrap(),
173 line: self.line,
174 column: self.column,
175 uid:self.uid,
176 //src_id: self.src_id,
177 })
178 }
179 /// do not try to create a `LBox<dyn Any>` structure with something like
180 ///```
181 /// let lb:LBox<dyn Any> = LBox::new(String::from("abc"),0,0);
182 ///```
183 /// This does not work as LBox is simply borrowing the underlying mechanics of
184 /// [Box] instead of re-creating them. Do instead:
185 ///```
186 /// let lb:LBox<dyn Any> = LBox::upcast(LBox::new(String::from("abc"),0,0));
187 ///```
188 /// upcast always returns a `LBox<dyn Any>`.
189 pub fn upcast<T:'t>(lb:LBox<T>) -> Self
190 {
191 let bx:Box<dyn Any+'t> = lb.exp; // this requires Any+'static ??
192 LBox { exp:bx, line:lb.line, column:lb.column, uid:lb.uid, }
193 }
194}// downcast/upcast for LBox
195
196///this is provided so `LBox<dyn Any>` can be used for the abstract syntax type.
197/// the default is a Lbox containing a static string.
198impl Default for LBox<dyn Any>
199{
200 fn default() -> Self {LBox::upcast(LBox::new("LBox<dyn Any> defaults to this string",0,0/*,0*/))}
201}
202
203impl<T:std::fmt::Debug> std::fmt::Debug for LBox<T> {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 std::fmt::Debug::fmt(&**self, f)
206// f.debug_struct("LBox")
207// .field("exp", &self.exp)
208// .field("y", &self.y)
209// .finish()
210 }
211}
212
213
214
215///Like LBox but encapsulates an Rc. Implements [Deref] and emulates the
216///[Rc::clone] function.
217pub struct LRc<T:?Sized>
218{
219 pub exp:Rc<T>,
220 pub line:u32,
221 pub column:u32,
222 //pub src_id:usize,
223}
224impl<T> LRc<T>
225{
226 pub fn new(e:T,ln:usize,col:usize /*,src:usize*/) -> LRc<T>
227 { LRc { exp:Rc::new(e), line:ln as u32, column:col as u32, /*src_id:src*/ } }
228 //pub fn set_src_id(&mut self, id:usize) {self.src_id=id;}
229 ///should be used to create a new LRc-expression that inherits
230 /// lexical information from existing LRc
231 pub fn transfer<U>(&self,e:U) -> LRc<U>
232 {
233 LRc::new(e,self.line(),self.column() /*,self.src_id*/)
234 }
235 ///uses [Rc::clone] to increase reference count of encapsulated Rc,
236 ///copies line, column and source_id information.
237 pub fn clone(lrc:&LRc<T>) -> LRc<T>
238 {
239 LRc {
240 exp: Rc::clone(&lrc.exp),
241 line: lrc.line,
242 column: lrc.column,
243 //src_id: lrc.src_id,
244 }
245 }//clone
246 pub fn line(&self) -> usize {self.line as usize}
247 //self.line.try_into().unwrap()}
248 pub fn column(&self) -> usize {self.column as usize}
249}
250
251impl<T:Clone> Clone for LRc<T>
252{
253 fn clone(&self) -> Self
254 {
255 LRc::clone(self)
256 }//clone
257}
258
259impl<T> Deref for LRc<T>
260{
261 type Target = T;
262 fn deref(&self) -> &Self::Target {
263 &self.exp
264 }
265}
266/* DerefMut is not implemented for Rc<T>
267impl<T> DerefMut for LRc<T>
268{
269 fn deref_mut(&mut self) -> &mut Self::Target {
270 &mut self.exp
271 }
272}
273*/
274impl<T:Default> Default for LRc<T>
275{
276 fn default() -> Self {LRc::new(T::default(),0,0/*,0*/)}
277}
278
279impl LRc<dyn Any+'static>
280{
281 /// emulates [LRc::downcast] function. Note that unlike Box::downcast,
282 ///an Option is returned here instead of a result.
283 pub fn downcast<U:'static>(self) -> Option<LRc<U>>
284 {
285 let rcdown = self.exp.downcast::<U>();
286 if let Err(_) = rcdown {return None;}
287 Some(LRc {
288 exp : rcdown.unwrap(),
289 line: self.line,
290 column: self.column,
291 //src_id: self.src_id,
292 })
293 }
294 /// upcasts `LRc<T>` to `LRc<dyn Any>`
295 pub fn upcast<T:'static>(lb:LRc<T>) -> Self
296 {
297 let bx:Rc<dyn Any> = lb.exp;
298 LRc { exp:bx, line:lb.line, column:lb.column, /*src_id:lb.src_id,*/ }
299 }
300}// downcast/upcast for LRc
301
302///this is required if `LRc<dyn Any>` is used for the abstract syntax type
303impl Default for LRc<dyn Any+'static>
304{
305 fn default() -> Self {LRc::upcast(LRc::new("LRc<dyn Any> defaults to this string",0,0 /*,0*/))}
306}
307
308impl<T:std::fmt::Debug> std::fmt::Debug for LRc<T> {
309 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
310 std::fmt::Debug::fmt(&**self, f)
311 }
312}
313
314/// Version of LBox that does not use a Box. This tuple struct contains
315/// a value of type T in the first position and a tuple consisting of
316/// (line, column, uid) numbers in the second position. The uid or
317/// *unique identifier* is a unique number placed in each LC structure
318/// created by the parser. It is useful for hashing information (such as
319/// inferred types) based on their source location. Multiple AST constructs
320/// may begin with the same line/column position, but the unique id will
321/// disambiguate them.
322/// This feature was added to Rustlr to support bumpalo-allocated ASTs.
323pub struct LC<T>(pub T,pub (u32,u32,u32));
324
325impl<T:Default> Default for LC<T> {
326 fn default() -> Self {LC(T::default(),(0,0,0))}
327}
328
329impl<T> Deref for LC<T>
330{
331 type Target = T;
332 fn deref(&self) -> &Self::Target {
333 &self.0
334 }
335}
336impl<T> DerefMut for LC<T>
337{
338 fn deref_mut(&mut self) -> &mut Self::Target {
339 &mut self.0
340 }
341}
342impl<T> AsRef<T> for LC<T>
343{
344 fn as_ref(&self) -> &T { &self.0 }
345}
346impl<T> AsMut<T> for LC<T>
347{
348 fn as_mut(&mut self) -> &mut T { &mut self.0 }
349}
350impl<T:std::fmt::Debug> std::fmt::Debug for LC<T> {
351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352 std::fmt::Debug::fmt(&self.0, f)
353 }
354}
355impl<T> LC<T>
356{
357 /// creates a new LC tuple struct in the form (value, (line,column,unique_id))
358 pub fn make(x:T,ln:usize,cl:usize,uid:u32) -> Self {
359 LC(x,(ln as u32,cl as u32,uid))
360 }
361 /// creates a new LC tuple struct in the form (value, (line,column))
362 /// with the unique_id field set to zero (for backwards compatibility)
363 pub fn new(x:T,ln:usize,cl:usize) -> Self {
364 LC(x,(ln as u32,cl as u32,0))
365 }
366 /// returns encapsulated line
367 pub fn line(&self) -> usize { (self.1.0) as usize }
368 /// returns encapsulated column
369 pub fn column(&self) -> usize { (self.1.1) as usize }
370 /// returns (line,column) as a pair of 32 values
371 pub fn lncl(&self) -> (u32,u32) { (self.1.0,self.1.1) }
372 /// returns unique id
373 pub fn uid(&self) -> u32 { self.1.2 }
374 /// returns value reference
375 pub fn value(&self) -> &T { &self.0 }
376 /// transfers line/column information to another LC
377 pub fn transfer<U>(&self,x:U) -> LC<U> {
378 LC::make(x,self.line(),self.column(),self.1.2)
379 }
380 /// consumes the LC enclosure and returns the enclosed value
381 pub fn consume(self) -> T { self.0 }
382}//impl LC
383
384impl<T:Default+?Sized> LC<T>
385{
386 ///transfers information from an [LBox] into an LC, consumes LBox
387 pub fn from_lbox(mut lb:LBox<T>) -> Self {
388 LC::make(lb.take(),lb.line(),lb.column(),lb.uid())
389 }
390}
391
392impl<T:Default+?Sized> LC<T>
393{
394 /// replaces the enclosed value with T::default() and returns the value
395 pub fn take(&mut self) -> T
396 { let mut res = T::default();
397 std::mem::swap(&mut res, self.as_mut());
398 res
399 }
400}
401
402/// Structure intended to support [bumpalo](https://docs.rs/bumpalo/latest/bumpalo/index.html) AST generations,
403///which allows recursive AST types to be defined using references instead of
404///smart pointers (LBox). The benefit of bump-allocated ASTs is the ability to
405///pattern match against nested, recursive structures, e.g.,
406///`Negative(Negative(x))`. The lifetime `'t` of a Bumper should be the same
407///as the lifetime of the parser's input.
408/// This structure is intended to become the
409///'external state' that's carried by the runtime parser (parser.exstate),
410///and therefore wraps another value (exstate) of the declared `externtype`.
411pub struct Bumper<'t,ET:Default>
412{
413 bump:Option<&'t Bump>,
414 exstate: ET,
415}//bumper struct
416impl<T:Default> Default for Bumper<'_,T> {
417 fn default() -> Self { Bumper{exstate:T::default(), bump:None} }
418}
419impl<'t,T:Default> Bumper<'t,T>
420{
421 /// sets the encapsulated [Bump](https://docs.rs/bumpalo/latest/bumpalo/struct.Bump.html) allocator
422 pub fn set(&mut self, b:&'t Bump) { self.bump = Some(b); }
423
424 /// tests if the allocator has been set
425 pub fn is_set(&self) -> bool { self.bump.is_some() }
426
427 /// returns pointer to the bump allocator. Warning: this function calls
428 /// unwrap and should only be called after [Bumper::set] has been called
429 pub fn get(&self)->&'t Bump { self.bump.expect("bump arena not set") }
430
431 /// bump-allocates x and returns a reference, which will live as long
432 /// as the bump allocator. Warning: this function calls unwrap and
433 /// will panic if the Bumper is not set.
434 pub fn make<S>(&self,x:S) -> &'t S {
435 self.get().alloc(x)
436 }
437
438 /// version of make that returns Option, but will not panic
439 pub fn make_safe<S>(&self,x:S) -> Option<&'t S> {
440 if self.bump.is_some() {Some(self.get().alloc(x))}
441 else {None}
442 }
443
444 /// version of make_safe that returns a mutable reference to the allocated
445 /// value
446 pub fn alloc<S>(&self,x:S) -> Option<&'t mut S> {
447 self.bump.map(|b|b.alloc(x))
448 }
449
450 /// returns a mut reference to the encapsulated "state" of type ET
451 pub fn state(&mut self) -> &mut T { &mut self.exstate }
452}//impl Bumper
453
454
455
456
457
458// [LBox] specific to [GenAbsyn] type, implements [Debug] and [Clone],
459// unlike a generic LBox
460type ABox = LBox<GenAbsyn>;
461
462
463/// Generic Abstract Syntax type: Rustlr offers the user the option
464/// of using a ready-made abstract syntax type that should be suitable for
465/// ordinary situations. Incorporates the usage of LBox so that abstract
466/// syntax trees always carry line/column information for error reporting and
467/// warnings. Rustlr will implement an option to produce a parser that
468/// uses GenAbsyn in conjunction with [ABox], and a custom parse_generic function
469/// that should simplify the process of parsing into abstract syntax.
470#[derive(Clone,Debug)]
471enum GenAbsyn
472{
473 Integer(i64),
474 BigInteger(String),
475 Float(f64),
476 Symbol(&'static str),
477 Keyword(&'static str),
478 Alphanum(String),
479 Stringlit(String),
480 Verbatim(String),
481 Uniop(usize,ABox),
482 Binop(usize,ABox,ABox),
483 Ternop(usize,ABox,ABox,ABox),
484 Sequence(usize,Vec<ABox>),
485 Partial(ABox,String), // error result, line/column/msg
486 NewLine,
487 Whitespaces(usize),
488 Nothing,
489}
490impl GenAbsyn
491{
492 fn is_complete(&self) -> bool
493 {
494 match self
495 {
496 GenAbsyn::Partial(_,_) => false,
497 GenAbsyn::Uniop(_,s) => {
498 println!("s.line {}{}",s.line,s.column);
499 s.is_complete()
500 },
501 GenAbsyn::Binop(_,a,b) => a.is_complete() && b.is_complete(),
502 GenAbsyn::Ternop(_,a,b,c) => a.is_complete() && b.is_complete() && c.is_complete(),
503 GenAbsyn::Sequence(_,v) => {
504 for x in v { if !x.is_complete() {return false; } }
505 true
506 }
507 _ => true,
508 }
509 }//is_complete
510}//impl GenAbsyn
511
512impl Default for GenAbsyn
513{
514 fn default() -> Self { GenAbsyn::Nothing }
515}//impl Default
516
517
518//const KEYWORDS:[&'static str;4] = ["if","while","let","lambda"];
519//const SYMBOLS:[&'static str;4] = ["==","(",")",":"];
520
521// don't know what to do with this yet
522
523/// Structure for configuring specific use of [GenAbsyn] type, which
524/// provides generic representations of binary, unary, ternary and
525/// vectorized operators. GenAbsyn also distinguishes keywords from
526/// other alphanumeric and non-alphanumeric symbols. Since these are
527/// provided from source code, &'static str is used instead of owned
528/// strings. The index of the corresponding &'static str in
529/// the static array OPERATORS will determine
530/// the usize index that identifies each Binop, Uniop, etc.
531struct Absyn_Statics<const N:usize,const M:usize,const P:usize>
532{
533 pub KEYWORDS: [&'static str; N],
534 pub SYMBOLS: [&'static str; M],
535 /// indices determine usize identifier of Binop, Uniop, Ternop, etc.
536 pub OPERATORS: [&'static str; P],
537 /// maps each string to corresponding index in KEYWORDS
538 pub Keyhash:HashMap<&'static str,usize>,
539 pub Symhash:HashMap<&'static str,usize>,
540 pub Ophash: HashMap<&'static str,usize>,
541}
542impl<const N:usize,const M:usize,const P:usize> Absyn_Statics<N,M,P>
543{
544 fn new(k:[&'static str; N],s:[&'static str;M],p:[&'static str;P])
545 -> Absyn_Statics<N,M,P>
546 {
547 let mut newas = Absyn_Statics {
548 KEYWORDS: k,
549 SYMBOLS: s,
550 OPERATORS:p,
551 Keyhash: HashMap::with_capacity(N),
552 Symhash: HashMap::with_capacity(M),
553 Ophash: HashMap::with_capacity(P),
554 };
555 for i in 0..N { newas.Keyhash.insert(k[i],i); }
556 for i in 0..M { newas.Symhash.insert(s[i],i); }
557 for i in 0..P { newas.Ophash.insert(p[i],i); }
558 return newas;
559 }//new
560
561 pub fn is_keyword(&self,k:&str) -> bool
562 { self.Keyhash.contains_key(k) }
563 pub fn is_symbol(&self,k:&str) -> bool
564 { self.Symhash.contains_key(k) }
565 pub fn is_operator(&self,k:&str) -> bool
566 { self.Ophash.contains_key(k) }
567}//impl Absyn_Statics
568
569
570/* //testing - did compile
571fn check(e:&GenAbsyn) -> bool {
572 match e {
573 Binop(3,x,_) => {
574 println!("Binop 3 not allowed on line {}, column {}",x.line,x.column);
575 false
576 },
577 Binop(i,a,b) => { check(a) && check(b) },
578 _ => true
579 }
580}
581*/
582
583/*
584///macro for creating [LBox] structures, for use in grammar semantic actions: each semantic action associated
585/// with a grammar rule is a Rust lambda expression of the form
586/// __|parser|{...}__
587/// of type __fn(&mut RuntimeParser) -> AT__ where AT is the type of the abstract
588/// syntax value defined for the grammar. __lbox!(e)__ expands to **parser.lb(e)**, calling the [RuntimeParser::lb] function.
589// The macro can also form an [ABox], which is an alias for LBox<GenAbsyn>
590#[macro_export]
591macro_rules! lbox {
592 ( $parser:expr,$x:expr ) => {
593 $parser.lb($x)
594 };
595}
596*/
597
598///macro for creating `LBox<dyn Any>` structures that can encapsulate any type
599///as abstract syntax. **Must** be called from within the semantic actions of
600///a grammar production rule.
601#[macro_export]
602macro_rules! lbup {
603 ( $x:expr ) => {
604 LBox::upcast($x)
605 };
606}
607
608/// macro for downcasting `LBox<dyn Any>` to `LBox<A>` for some
609/// concrete type A. Must be called
610/// from within the semantic actions of grammar productions. **Warning:**
611/// **unwrap** is called within the macro
612#[macro_export]
613macro_rules! lbdown {
614 ( $x:expr,$t:ty ) => {
615 $x.downcast::<$t>().unwrap()
616 };
617}
618
619/// similar to [lbdown], but also extracts the boxed expression
620#[macro_export]
621macro_rules! lbget {
622 ( $x:expr,$t:ty ) => {
623 *$x.downcast::<$t>().unwrap().exp
624 };
625}
626/// just extract value from LBox
627#[macro_export]
628macro_rules! unbox {
629 ( $x:expr ) => {
630 *$x.exp
631 };
632}
633
634/// macro for creating an [LBox] from a [crate::StackedItem] ($si) popped from
635/// the parse stack; should be called from within the semantics actions of
636/// a grammar to accurately encode lexical information.
637#[macro_export]
638macro_rules! makelbox {
639 ($si:expr, $e:expr) => {
640 LBox::new($e,$si.line,$si.column)
641 };
642}
643
644/// similar to [makelbox] but creates an [LRc] from lexical information
645/// inside stack item $si
646#[macro_export]
647macro_rules! makelrc {
648 ($si:expr, $e:expr) => {
649 LRc::new($e,$si.line,$si.column)
650 };
651}
652
653/*
654// just to see if it compiles
655struct BB(usize);
656fn testing()
657{
658 let bb1:&dyn Any = &BB(1);
659 let bb2:Box<dyn Any> = Box::new(BB(2));
660 let bx:Box<dyn Any> = Box::new(String::from("abc"));
661 //let b1:LBox<dyn Any> = LBox::new(BB(1),0,0,0); // doesn't work
662 //let b3:LBox<dyn Any> = LBox::frombox(bb2,0,0,0); // works!
663 let b5:LBox<BB> = LBox::new(BB(100),0,0,0);
664 let b6:LBox<dyn Any> = LBox::upcast(b5);
665 let b4:LBox<BB> = b6.downcast::<BB>().unwrap();
666 let lb:LBox<dyn Any> = LBox::upcast(LBox::new(String::from("abc"),0,0,0));
667 //let lbd:LBox<dyn Default> = LBox::upcast(LBox::new(String::from("ab"),0,0,0));
668}
669*/