Struct Ident

Source
pub struct Ident { /* private fields */ }
Expand description

An identifier consisting of alphanumeric characters and underscores, and starting with an alphabetic character or an underscore.

Implementations§

Source§

impl Ident

Source

pub const fn string(&self) -> &String

Returns the text that makes up the identifier.

Examples found in repository?
examples/lox/resolver.rs (line 40)
38    fn declare(&mut self, name: &Ident) {
39        if let Some(scope) = self.scopes.last_mut() {
40            if scope.contains_key(name.string()) {
41                self.error(new_error(
42                    "Already a variable with this name in scope".to_string(),
43                    name,
44                    error_codes::SHADOW,
45                ));
46            } else {
47                scope.insert(name.string().to_owned(), false);
48            }
49        }
50    }
51
52    fn define(&mut self, name: &Ident) {
53        if let Some(scope) = self.scopes.last_mut() {
54            scope.insert(name.string().to_owned(), true);
55        }
56    }
57
58    fn resolve_local(&self, name: &Ident, distance: &Cell<Option<usize>>) {
59        for (i, scope) in self.scopes.iter().enumerate().rev() {
60            if scope.contains_key(name.string()) {
61                distance.set(Some(self.scopes.len() - 1 - i));
62                return;
63            }
64        }
65    }
66
67    fn error(&mut self, error: Error) {
68        if let Some(existing_error) = &mut self.error {
69            existing_error.add(error);
70        } else {
71            self.error = Some(error);
72        }
73    }
74
75    fn begin_scope(&mut self) {
76        self.scopes.push(HashMap::new());
77    }
78
79    fn end_scope(&mut self) {
80        self.scopes.pop();
81    }
82}
83
84impl Expr {
85    fn resolve(&self, state: &mut State) {
86        match self {
87            Expr::Assign {
88                name,
89                value,
90                distance,
91            } => {
92                value.resolve(state);
93                state.resolve_local(name, distance);
94            }
95            Expr::Binary(binary) => {
96                binary.left().resolve(state);
97                binary.right().resolve(state);
98            }
99            Expr::Call {
100                callee,
101                paren: _,
102                arguments,
103            } => {
104                callee.resolve(state);
105                for argument in arguments {
106                    argument.resolve(state);
107                }
108            }
109            Expr::Get { object, name: _ } => object.resolve(state),
110            Expr::Group(expr) => expr.resolve(state),
111            Expr::Literal(_) => {}
112            Expr::Logical(logical) => {
113                logical.left().resolve(state);
114                logical.right().resolve(state);
115            }
116            Expr::Set {
117                object,
118                name: _,
119                value,
120            } => {
121                object.resolve(state);
122                value.resolve(state);
123            }
124            Expr::Super {
125                keyword,
126                distance,
127                dot: _,
128                method: _,
129            } => {
130                if state.current_class == ClassType::None {
131                    state.error(new_error(
132                        "Can't use 'super' outside of a class".to_string(),
133                        keyword,
134                        error_codes::INVALID_SUPER,
135                    ));
136                } else if state.current_class == ClassType::Class {
137                    state.error(new_error(
138                        "Can't use 'super' in a class with no superclass".to_string(),
139                        keyword,
140                        error_codes::INVALID_SUPER,
141                    ));
142                }
143                state.resolve_local(keyword.ident(), distance);
144            }
145            Expr::This { keyword, distance } => {
146                if state.current_class == ClassType::None {
147                    state.error(new_error(
148                        "Can't use 'this' outside of a class".to_string(),
149                        keyword,
150                        error_codes::THIS_OUTSIDE_CLASS,
151                    ));
152                }
153
154                state.resolve_local(keyword.ident(), distance);
155            }
156            Expr::Unary(unary) => unary.right().resolve(state),
157            Expr::Variable { name, distance } => {
158                if let Some(scope) = state.scopes.last() {
159                    if scope.get(name.string()) == Some(&false) {
160                        state.error(new_error(
161                            "Can't read a variable in its own intialiser".to_string(),
162                            name,
163                            error_codes::INVALID_INITIALISER,
164                        ));
165                    }
166                }
167                state.resolve_local(name, distance);
168            }
169        }
170    }
171}
172
173impl Function {
174    fn resolve(&self, state: &mut State, kind: FunctionType) {
175        let enclosing = state.current_function;
176        state.current_function = kind;
177        state.begin_scope();
178        for param in &self.params {
179            state.declare(param);
180            state.define(param);
181        }
182        for stmt in &self.body {
183            stmt.resolve(state);
184        }
185        state.end_scope();
186        state.current_function = enclosing;
187    }
188}
189
190impl Stmt {
191    fn resolve(&self, state: &mut State) {
192        match self {
193            Stmt::Block(stmts) => {
194                state.begin_scope();
195                for stmt in stmts {
196                    stmt.resolve(state);
197                }
198                state.end_scope();
199            }
200            Stmt::Class {
201                name,
202                superclass,
203                superclass_distance,
204                methods,
205            } => {
206                let enclosing = state.current_class;
207                state.current_class = ClassType::Class;
208
209                state.declare(name);
210                state.define(name);
211
212                if let Some(superclass) = superclass {
213                    if name.string() == superclass.string() {
214                        state.error(new_error(
215                            "A class can't inherit from itself".to_string(),
216                            superclass,
217                            error_codes::CYCLICAL_INHERITANCE,
218                        ));
219                    }
220
221                    state.current_class = ClassType::SubClass;
222
223                    state.resolve_local(superclass, superclass_distance);
224
225                    state.begin_scope();
226                    state
227                        .scopes
228                        .last_mut()
229                        .unwrap()
230                        .insert("super".to_string(), true);
231                }
232
233                state.begin_scope();
234                state
235                    .scopes
236                    .last_mut()
237                    .unwrap()
238                    .insert("this".to_string(), true);
239
240                for method in methods {
241                    let kind = if method.name.string() == "init" {
242                        FunctionType::Initialiser
243                    } else {
244                        FunctionType::Method
245                    };
246                    method.resolve(state, kind);
247                }
248
249                state.end_scope();
250
251                if superclass.is_some() {
252                    state.end_scope();
253                }
254
255                state.current_class = enclosing;
256            }
257            Stmt::Expr(expr) | Stmt::Print(expr) => expr.resolve(state),
258            Stmt::Function(function) => {
259                state.declare(&function.name);
260                state.declare(&function.name);
261                function.resolve(state, FunctionType::Function);
262            }
263            Stmt::If {
264                condition,
265                then_branch,
266                else_branch,
267            } => {
268                condition.resolve(state);
269                then_branch.resolve(state);
270                if let Some(else_branch) = else_branch {
271                    else_branch.resolve(state);
272                }
273            }
274            Stmt::Return { keyword, value } => {
275                if state.current_function == FunctionType::None {
276                    state.error(new_error(
277                        "Can't return from top-level code".to_string(),
278                        keyword,
279                        error_codes::RETURN_OUTSIDE_FUNCTION,
280                    ));
281                }
282                if let Some(value) = value {
283                    value.resolve(state);
284                }
285            }
286            Stmt::Variable { name, initialiser } => {
287                state.declare(name);
288                if let Some(initialiser) = initialiser {
289                    initialiser.resolve(state);
290                }
291                state.define(name);
292            }
293            Stmt::While { condition, body } => {
294                condition.resolve(state);
295                body.resolve(state);
296            }
297        }
298    }
More examples
Hide additional examples
examples/lox/interpreter.rs (line 124)
111    fn call(&self, arguments: Vec<Value>, parentheses: &Parentheses) -> Result<Value> {
112        let state = self.closure.start_scope();
113        if self.declaration.params.len() != arguments.len() {
114            return Err(arity_error(
115                parentheses,
116                self.declaration.params.len(),
117                arguments.len(),
118            ));
119        }
120        for (name, arg) in self.declaration.params.iter().zip(arguments) {
121            state
122                .environment
123                .borrow_mut()
124                .define(name.string().to_owned(), arg);
125        }
126        for stmt in &self.declaration.body {
127            if let Some(value) = stmt.execute(&state)? {
128                return Ok(value);
129            }
130        }
131        Ok(Value::Nil)
132    }
133
134    fn bind(&self, instance: &'static RefCell<Instance>) -> Function {
135        let scope = self.closure.start_scope();
136        scope
137            .environment
138            .borrow_mut()
139            .define("this".to_string(), Value::Instance(instance));
140        Function {
141            declaration: self.declaration.clone(),
142            closure: scope,
143            is_initialiser: self.is_initialiser,
144        }
145    }
146}
147
148impl PartialEq for Function {
149    fn eq(&self, other: &Self) -> bool {
150        self.declaration == other.declaration
151    }
152}
153
154#[derive(Debug, Clone, PartialEq)]
155struct Class {
156    name: String,
157    superclass: Option<Rc<Class>>,
158    methods: HashMap<String, Function>,
159}
160
161impl Class {
162    const fn new(
163        name: String,
164        superclass: Option<Rc<Class>>,
165        methods: HashMap<String, Function>,
166    ) -> Class {
167        Class {
168            name,
169            superclass,
170            methods,
171        }
172    }
173
174    fn find_method(&self, name: &str) -> Option<&Function> {
175        self.methods.get(name).map_or_else(
176            || {
177                self.superclass
178                    .as_ref()
179                    .and_then(|superclass| superclass.find_method(name))
180            },
181            Some,
182        )
183    }
184
185    fn arity(&self) -> usize {
186        self.find_method("init")
187            .map_or(0, |f| f.declaration.params.len())
188    }
189}
190
191#[derive(Clone, PartialEq)]
192struct Instance {
193    class: Rc<Class>,
194    fields: HashMap<String, Value>,
195}
196
197impl Instance {
198    fn new(class: Rc<Class>) -> Instance {
199        Instance {
200            class,
201            fields: HashMap::new(),
202        }
203    }
204
205    fn set(&mut self, name: &Ident, value: Value) {
206        self.fields.insert(name.string().to_string(), value);
207    }
208}
209
210fn get(instance: &'static RefCell<Instance>, name: &Ident) -> Result<Value> {
211    let this = instance.borrow();
212    if let Some(value) = this.fields.get(name.string()) {
213        Ok(value.to_owned())
214    } else if let Some(function) = this.class.find_method(name.string()) {
215        Ok(Value::Function(function.bind(instance)))
216    } else {
217        Err(new_error(
218            format!("Undefined property '{}'", name.string()),
219            name,
220            error_codes::UNDEFINED_NAME,
221        ))
222    }
223}
224
225impl fmt::Debug for Instance {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        f.debug_struct("Instance")
228            .field("class", &self.class.name)
229            .field("fields", &self.fields)
230            .finish()
231    }
232}
233
234#[derive(Debug, Clone, PartialEq)]
235enum Value {
236    Nil,
237    String(String),
238    Number(f64),
239    Bool(bool),
240    Native(NativeFunction),
241    Function(Function),
242    Class(Rc<Class>),
243    Instance(&'static RefCell<Instance>),
244}
245
246fn arity_error(parentheses: &Parentheses, expected: usize, actual: usize) -> Error {
247    new_error(
248        format!("Expected {expected} arguments but got {actual}"),
249        parentheses.span().to_owned(),
250        error_codes::INCORRECT_ARITY,
251    )
252}
253
254impl Value {
255    const fn as_class(&self) -> Option<&Rc<Class>> {
256        if let Value::Class(class) = self {
257            Some(class)
258        } else {
259            None
260        }
261    }
262
263    const fn as_instance(&self) -> Option<&'static RefCell<Instance>> {
264        if let Value::Instance(instance) = self {
265            Some(*instance)
266        } else {
267            None
268        }
269    }
270
271    const fn is_truthy(&self) -> bool {
272        !matches!(self, Value::Nil | Value::Bool(false))
273    }
274
275    fn add(&self, op: &Punct!["+"], other: &Value) -> Result<Value> {
276        match (self, other) {
277            (Value::Number(n1), Value::Number(n2)) => Ok(Value::Number(n1 + n2)),
278            (Value::String(s1), Value::String(s2)) => Ok(Value::String(s1.to_owned() + s2)),
279            _ => Err(new_error(
280                format!("Can't add '{self}' to '{other}'"),
281                op,
282                error_codes::TYPE_ERROR,
283            )),
284        }
285    }
286
287    fn sub(&self, op: &Punct!["-"], other: &Value) -> Result<Value> {
288        if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
289            Ok(Value::Number(n1 - n2))
290        } else {
291            Err(new_error(
292                format!("Can't subtract '{other}' from '{self}'"),
293                op,
294                error_codes::TYPE_ERROR,
295            ))
296        }
297    }
298
299    fn mul(&self, op: &Punct!["*"], other: &Value) -> Result<Value> {
300        if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
301            Ok(Value::Number(n1 * n2))
302        } else {
303            Err(new_error(
304                format!("Can't multiply '{self}' by '{other}'"),
305                op,
306                error_codes::TYPE_ERROR,
307            ))
308        }
309    }
310
311    fn div(&self, op: &Punct!["/"], other: &Value) -> Result<Value> {
312        if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
313            Ok(Value::Number(n1 / n2))
314        } else {
315            Err(new_error(
316                format!("Can't divide '{other}' by '{self}'"),
317                op,
318                error_codes::TYPE_ERROR,
319            ))
320        }
321    }
322
323    fn neg(&self, op: &Punct!["-"]) -> Result<Value> {
324        if let Value::Number(n) = self {
325            Ok(Value::Number(-n))
326        } else {
327            Err(new_error(
328                format!("Can't negate '{self}'"),
329                op,
330                error_codes::TYPE_ERROR,
331            ))
332        }
333    }
334
335    fn cmp<T: Token>(&self, op: &T, other: &Value) -> Result<Ordering> {
336        if self == other {
337            return Ok(Ordering::Equal);
338        }
339
340        match (self, other) {
341            (Value::String(s1), Value::String(s2)) => Ok(s1.cmp(s2).into()),
342            (Value::Number(n1), Value::Number(n2)) => Ok(n1.partial_cmp(n2).into()),
343            (Value::Bool(b1), Value::Bool(b2)) => Ok(b1.cmp(b2).into()),
344            _ => Err(new_error(
345                format!("Can't compare '{self}' with '{other}'"),
346                op,
347                error_codes::TYPE_ERROR,
348            )),
349        }
350    }
351
352    fn call(&self, arguments: Vec<Value>, parentheses: &Parentheses) -> Result<Value> {
353        match self {
354            Value::Native(NativeFunction {
355                function, arity, ..
356            }) => {
357                if *arity != arguments.len() {
358                    return Err(arity_error(parentheses, *arity, arguments.len()));
359                }
360                function(arguments)
361            }
362            Value::Function(function) => function.call(arguments, parentheses),
363            Value::Class(class) => {
364                if class.arity() != arguments.len() {
365                    return Err(arity_error(parentheses, class.arity(), arguments.len()));
366                }
367
368                let instance = allocate(Instance::new(Rc::clone(class)));
369                if let Some(initialiser) = class.find_method("init") {
370                    initialiser.bind(instance).call(arguments, parentheses)?;
371                }
372                Ok(Value::Instance(instance))
373            }
374            Value::Nil
375            | Value::String(_)
376            | Value::Number(_)
377            | Value::Bool(_)
378            | Value::Instance(_) => Err(new_error(
379                format!("Can't call '{self}'"),
380                parentheses.span().clone(),
381                error_codes::TYPE_ERROR,
382            )),
383        }
384    }
385}
386
387impl fmt::Display for Value {
388    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389        match self {
390            Value::Nil => f.write_str("nil"),
391            Value::String(s) => f.write_str(s),
392            Value::Number(n) => write!(f, "{n}"),
393            Value::Bool(b) => write!(f, "{b}"),
394            Value::Native(NativeFunction { name, .. }) => write!(f, "<native fn '{name}'>"),
395            Value::Function(Function {
396                declaration: FunctionDecl { name, .. },
397                ..
398            }) => write!(f, "<fn {}>", name.string()),
399            Value::Class(class) => f.write_str(&class.name),
400            Value::Instance(instance) => write!(f, "'{}' instance", instance.borrow().class.name),
401        }
402    }
403}
404
405#[derive(Debug, Clone)]
406struct State {
407    environment: Rc<RefCell<Environment>>,
408    globals: Rc<RefCell<Environment>>,
409}
410
411impl State {
412    fn new() -> Self {
413        let mut values = HashMap::new();
414
415        values.insert(
416            "clock".to_string(),
417            Value::Native(NativeFunction {
418                function: natives::clock,
419                arity: 0,
420                name: "clock",
421            }),
422        );
423
424        let environment = Rc::new(RefCell::new(Environment {
425            values,
426            enclosing: None,
427            sub: vec![],
428            mark: Cell::new(false),
429        }));
430
431        State {
432            environment: Rc::clone(&environment),
433            globals: environment,
434        }
435    }
436
437    #[must_use]
438    fn start_scope(&self) -> State {
439        let environment = Rc::new(RefCell::new(Environment {
440            values: HashMap::new(),
441            enclosing: Some(Rc::clone(&self.environment)),
442            sub: vec![],
443            mark: Cell::new(false),
444        }));
445        self.environment
446            .borrow_mut()
447            .sub
448            .push(Rc::downgrade(&environment));
449        State {
450            environment,
451            globals: Rc::clone(&self.globals),
452        }
453    }
454
455    fn super_scope(self) -> Option<State> {
456        Some(State {
457            environment: Rc::clone(self.environment.borrow().enclosing.as_ref()?),
458            globals: self.globals,
459        })
460    }
461}
462
463fn allocate<T>(value: T) -> &'static RefCell<T> {
464    Box::leak(Box::new(RefCell::new(value)))
465}
466
467struct Environment {
468    values: HashMap<String, Value>,
469    enclosing: Option<Rc<RefCell<Environment>>>,
470    sub: Vec<Weak<RefCell<Environment>>>,
471    mark: Cell<bool>,
472}
473
474impl Environment {
475    fn get(&self, name: &Ident) -> Result<Value> {
476        self.values.get(name.string()).map_or_else(
477            || {
478                self.enclosing.as_ref().map_or_else(
479                    || {
480                        Err(new_error(
481                            format!("Undefined variable '{}'", name.string()),
482                            name,
483                            error_codes::UNDEFINED_NAME,
484                        ))
485                    },
486                    |enclosing| enclosing.borrow().get(name),
487                )
488            },
489            |value| Ok(value.to_owned()),
490        )
491    }
492
493    fn get_at(&self, name: &Ident, distance: usize) -> Result<Value> {
494        if distance == 0 {
495            self.get(name)
496        } else {
497            self.enclosing
498                .as_ref()
499                .unwrap()
500                .borrow()
501                .get_at(name, distance - 1)
502        }
503    }
504
505    fn define(&mut self, name: String, value: Value) {
506        self.values.insert(name, value);
507    }
508
509    fn assign(&mut self, name: &Ident, value: Value) -> Result<()> {
510        if self.values.contains_key(name.string()) {
511            self.values.insert(name.string().clone(), value);
512            Ok(())
513        } else if let Some(enclosing) = &self.enclosing {
514            enclosing.borrow_mut().assign(name, value)
515        } else {
516            Err(new_error(
517                format!("Undefined variable '{}'", name.string()),
518                name,
519                error_codes::UNDEFINED_NAME,
520            ))
521        }
522    }
523
524    fn assign_at(&mut self, name: &Ident, value: Value, distance: usize) -> Result<()> {
525        if distance == 0 {
526            self.assign(name, value)
527        } else {
528            self.enclosing
529                .as_ref()
530                .unwrap()
531                .borrow_mut()
532                .assign_at(name, value, distance - 1)
533        }
534    }
535}
536
537struct EnvValuesDebug<'a>(&'a HashMap<String, Value>);
538
539impl fmt::Debug for EnvValuesDebug<'_> {
540    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541        f.debug_map()
542            .entries(self.0.iter().map(|(k, v)| (k, v.to_string())))
543            .finish()
544    }
545}
546
547impl fmt::Debug for Environment {
548    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549        f.debug_struct("Environment")
550            .field("values", &EnvValuesDebug(&self.values))
551            .field("enclosing", &self.enclosing)
552            .field("sub", &self.sub)
553            .field("mark", &self.mark)
554            .finish()
555    }
556}
557
558impl Binary {
559    fn evaluate(&self, state: &State) -> Result<Value> {
560        match self {
561            Binary::Mul(left, op, right) => left.evaluate(state)?.mul(op, &right.evaluate(state)?),
562            Binary::Div(left, op, right) => left.evaluate(state)?.div(op, &right.evaluate(state)?),
563            Binary::Add(left, op, right) => left.evaluate(state)?.add(op, &right.evaluate(state)?),
564            Binary::Sub(left, op, right) => left.evaluate(state)?.sub(op, &right.evaluate(state)?),
565            Binary::Equal(left, _, right) => {
566                Ok(Value::Bool(left.evaluate(state)? == right.evaluate(state)?))
567            }
568            Binary::NotEqual(left, _, right) => {
569                Ok(Value::Bool(left.evaluate(state)? != right.evaluate(state)?))
570            }
571            Binary::Greater(left, op, right) => Ok(Value::Bool(
572                left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.gt(),
573            )),
574            Binary::GreaterEqual(left, op, right) => Ok(Value::Bool(
575                left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.ge(),
576            )),
577            Binary::Less(left, op, right) => Ok(Value::Bool(
578                left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.lt(),
579            )),
580            Binary::LessEqual(left, op, right) => Ok(Value::Bool(
581                left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.le(),
582            )),
583        }
584    }
585}
586
587impl Literal {
588    fn evaluate(&self) -> Value {
589        match self {
590            Literal::False(_) => Value::Bool(false),
591            Literal::Float(value) => Value::Number(value.value()),
592            #[allow(clippy::cast_precision_loss)]
593            Literal::Int(value) => Value::Number(value.value() as f64),
594            Literal::Nil(_) => Value::Nil,
595            Literal::String(string) => Value::String(string.string().clone()),
596            Literal::True(_) => Value::Bool(true),
597        }
598    }
599}
600
601impl Logical {
602    fn evaluate(&self, state: &State) -> Result<Value> {
603        match self {
604            Logical::And(left, _, right) => {
605                let left = left.evaluate(state)?;
606                if left.is_truthy() {
607                    Ok(left)
608                } else {
609                    right.evaluate(state)
610                }
611            }
612            Logical::Or(left, _, right) => {
613                let left = left.evaluate(state)?;
614                if left.is_truthy() {
615                    right.evaluate(state)
616                } else {
617                    Ok(left)
618                }
619            }
620        }
621    }
622}
623
624impl Unary {
625    fn evaluate(&self, state: &State) -> Result<Value> {
626        match self {
627            Unary::Neg(op, expr) => expr.evaluate(state)?.neg(op),
628            Unary::Not(_, expr) => Ok(Value::Bool(!expr.evaluate(state)?.is_truthy())),
629        }
630    }
631}
632
633impl Expr {
634    fn evaluate(&self, state: &State) -> Result<Value> {
635        match self {
636            Expr::Assign {
637                name,
638                value,
639                distance,
640            } => {
641                let value = value.evaluate(state)?;
642                if let Some(distance) = distance.get() {
643                    state
644                        .environment
645                        .borrow_mut()
646                        .assign_at(name, value.clone(), distance)?;
647                } else {
648                    state.globals.borrow_mut().assign(name, value.clone())?;
649                }
650                Ok(value)
651            }
652            Expr::Binary(binary) => binary.evaluate(state),
653            Expr::Call {
654                callee,
655                paren,
656                arguments,
657            } => {
658                let callee = callee.evaluate(state)?;
659                let mut evaluated_args = Vec::with_capacity(arguments.len());
660                for arg in arguments {
661                    evaluated_args.push(arg.evaluate(state)?);
662                }
663                callee.call(evaluated_args, paren)
664            }
665            Expr::Get { object, name } => {
666                if let Value::Instance(instance) = object.evaluate(state)? {
667                    get(instance, name)
668                } else {
669                    Err(new_error(
670                        "Only instances have properties".to_string(),
671                        name,
672                        error_codes::TYPE_ERROR,
673                    ))
674                }
675            }
676            Expr::Group(expr) => expr.evaluate(state),
677            Expr::Literal(literal) => Ok(literal.evaluate()),
678            Expr::Logical(logical) => logical.evaluate(state),
679            Expr::Set {
680                object,
681                name,
682                value,
683            } => {
684                if let Value::Instance(instance) = object.evaluate(state)? {
685                    let value = value.evaluate(state)?;
686                    instance.borrow_mut().set(name, value.clone());
687                    Ok(value)
688                } else {
689                    Err(new_error(
690                        "Only instances have fields".to_string(),
691                        name,
692                        error_codes::TYPE_ERROR,
693                    ))
694                }
695            }
696            Expr::Super {
697                keyword,
698                distance,
699                dot: _,
700                method,
701            } => {
702                let superclass = state
703                    .environment
704                    .borrow()
705                    .get_at(keyword.ident(), distance.clone().into_inner().unwrap())?;
706
707                let object = state.environment.borrow().get_at(
708                    &Ident::new("this".to_string(), keyword.span().clone()),
709                    distance.clone().into_inner().unwrap() - 1,
710                )?;
711
712                superclass
713                    .as_class()
714                    .unwrap()
715                    .find_method(method.string())
716                    .map_or_else(
717                        || {
718                            Err(new_error(
719                                format!("Undefined property '{}'", method.string()),
720                                method,
721                                error_codes::UNDEFINED_NAME,
722                            ))
723                        },
724                        |method| Ok(Value::Function(method.bind(object.as_instance().unwrap()))),
725                    )
726            }
727            Expr::This { keyword, distance } => distance.get().map_or_else(
728                || state.globals.borrow().get(keyword.ident()),
729                |distance| state.environment.borrow().get_at(keyword.ident(), distance),
730            ),
731            Expr::Unary(unary) => unary.evaluate(state),
732            Expr::Variable { name, distance } => distance.get().map_or_else(
733                || state.globals.borrow().get(name),
734                |distance| state.environment.borrow().get_at(name, distance),
735            ),
736        }
737    }
738}
739
740macro_rules! propagate_return {
741    ( $expr:expr ) => {
742        if let Some(_tmp) = $expr {
743            return Ok(Some(_tmp));
744        }
745    };
746}
747
748impl Stmt {
749    fn execute(&self, state: &State) -> Result<Option<Value>> {
750        match self {
751            Stmt::Block(stmts) => {
752                let inner_state = state.start_scope();
753                for stmt in stmts {
754                    propagate_return!(stmt.execute(&inner_state)?);
755                }
756            }
757            Stmt::Class {
758                name,
759                superclass,
760                superclass_distance,
761                methods,
762            } => {
763                let superclass = if let Some(superclass_name) = superclass {
764                    let superclass = Expr::Variable {
765                        name: superclass_name.clone(),
766                        distance: superclass_distance.clone(),
767                    }
768                    .evaluate(state)?;
769                    if let Value::Class(superclass) = superclass {
770                        Some(superclass)
771                    } else {
772                        return Err(new_error(
773                            "Superclass must be a class".to_string(),
774                            superclass_name,
775                            error_codes::INHERIT_FROM_VALUE,
776                        ));
777                    }
778                } else {
779                    None
780                };
781
782                state
783                    .environment
784                    .borrow_mut()
785                    .define(name.string().to_owned(), Value::Nil);
786
787                let superclass_is_some = superclass.is_some();
788                let mut state = superclass.as_ref().map_or_else(
789                    || state.clone(),
790                    |superclass| {
791                        let state = state.start_scope();
792                        state
793                            .environment
794                            .borrow_mut()
795                            .define("super".to_string(), Value::Class(Rc::clone(superclass)));
796                        state
797                    },
798                );
799
800                let methods = methods
801                    .iter()
802                    .map(|declaration| {
803                        (
804                            declaration.name.string().to_owned(),
805                            Function::new(
806                                declaration.clone(),
807                                state.clone(),
808                                declaration.name.string() == "init",
809                            ),
810                        )
811                    })
812                    .collect();
813                let class = Class::new(name.string().to_owned(), superclass, methods);
814
815                if superclass_is_some {
816                    state = state.super_scope().unwrap();
817                }
818
819                state
820                    .environment
821                    .borrow_mut()
822                    .assign(name, Value::Class(Rc::new(class)))?;
823            }
824            Stmt::Expr(expr) => {
825                expr.evaluate(state)?;
826            }
827            Stmt::Function(function) => {
828                let value =
829                    Value::Function(Function::new(function.to_owned(), state.clone(), false));
830                state
831                    .environment
832                    .borrow_mut()
833                    .define(function.name.string().to_owned(), value);
834            }
835            Stmt::If {
836                condition,
837                then_branch,
838                else_branch,
839            } => {
840                if condition.evaluate(state)?.is_truthy() {
841                    propagate_return!(then_branch.execute(state)?);
842                } else if let Some(else_branch) = else_branch {
843                    propagate_return!(else_branch.execute(state)?);
844                }
845            }
846            Stmt::Print(expr) => {
847                let value = expr.evaluate(state)?;
848                println!("{value}");
849            }
850            Stmt::Return { keyword: _, value } => {
851                return Ok(Some(
852                    value
853                        .as_ref()
854                        .map_or(Ok(Value::Nil), |v| v.evaluate(state))?,
855                ));
856            }
857            Stmt::Variable { name, initialiser } => {
858                let value = if let Some(initialiser) = initialiser {
859                    initialiser.evaluate(state)?
860                } else {
861                    Value::Nil
862                };
863                state
864                    .environment
865                    .borrow_mut()
866                    .define(name.string().to_owned(), value);
867            }
868            Stmt::While { condition, body } => {
869                while condition.evaluate(state)?.is_truthy() {
870                    propagate_return!(body.execute(state)?);
871                }
872            }
873        }
874
875        Ok(None)
876    }
Source

pub const fn new(string: String, span: Span) -> Ident

Creates a new identifier in the given ParseStream with the given string.

Examples found in repository?
examples/lox/interpreter.rs (line 708)
634    fn evaluate(&self, state: &State) -> Result<Value> {
635        match self {
636            Expr::Assign {
637                name,
638                value,
639                distance,
640            } => {
641                let value = value.evaluate(state)?;
642                if let Some(distance) = distance.get() {
643                    state
644                        .environment
645                        .borrow_mut()
646                        .assign_at(name, value.clone(), distance)?;
647                } else {
648                    state.globals.borrow_mut().assign(name, value.clone())?;
649                }
650                Ok(value)
651            }
652            Expr::Binary(binary) => binary.evaluate(state),
653            Expr::Call {
654                callee,
655                paren,
656                arguments,
657            } => {
658                let callee = callee.evaluate(state)?;
659                let mut evaluated_args = Vec::with_capacity(arguments.len());
660                for arg in arguments {
661                    evaluated_args.push(arg.evaluate(state)?);
662                }
663                callee.call(evaluated_args, paren)
664            }
665            Expr::Get { object, name } => {
666                if let Value::Instance(instance) = object.evaluate(state)? {
667                    get(instance, name)
668                } else {
669                    Err(new_error(
670                        "Only instances have properties".to_string(),
671                        name,
672                        error_codes::TYPE_ERROR,
673                    ))
674                }
675            }
676            Expr::Group(expr) => expr.evaluate(state),
677            Expr::Literal(literal) => Ok(literal.evaluate()),
678            Expr::Logical(logical) => logical.evaluate(state),
679            Expr::Set {
680                object,
681                name,
682                value,
683            } => {
684                if let Value::Instance(instance) = object.evaluate(state)? {
685                    let value = value.evaluate(state)?;
686                    instance.borrow_mut().set(name, value.clone());
687                    Ok(value)
688                } else {
689                    Err(new_error(
690                        "Only instances have fields".to_string(),
691                        name,
692                        error_codes::TYPE_ERROR,
693                    ))
694                }
695            }
696            Expr::Super {
697                keyword,
698                distance,
699                dot: _,
700                method,
701            } => {
702                let superclass = state
703                    .environment
704                    .borrow()
705                    .get_at(keyword.ident(), distance.clone().into_inner().unwrap())?;
706
707                let object = state.environment.borrow().get_at(
708                    &Ident::new("this".to_string(), keyword.span().clone()),
709                    distance.clone().into_inner().unwrap() - 1,
710                )?;
711
712                superclass
713                    .as_class()
714                    .unwrap()
715                    .find_method(method.string())
716                    .map_or_else(
717                        || {
718                            Err(new_error(
719                                format!("Undefined property '{}'", method.string()),
720                                method,
721                                error_codes::UNDEFINED_NAME,
722                            ))
723                        },
724                        |method| Ok(Value::Function(method.bind(object.as_instance().unwrap()))),
725                    )
726            }
727            Expr::This { keyword, distance } => distance.get().map_or_else(
728                || state.globals.borrow().get(keyword.ident()),
729                |distance| state.environment.borrow().get_at(keyword.ident(), distance),
730            ),
731            Expr::Unary(unary) => unary.evaluate(state),
732            Expr::Variable { name, distance } => distance.get().map_or_else(
733                || state.globals.borrow().get(name),
734                |distance| state.environment.borrow().get_at(name, distance),
735            ),
736        }
737    }

Trait Implementations§

Source§

impl Clone for Ident

Source§

fn clone(&self) -> Ident

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Ident

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Hash for Ident

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Ident

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl Parse for Ident

Source§

fn parse(input: ParseStream<'_>) -> Result<Self>

Parses the input into this type. Read more
Source§

impl PartialEq for Ident

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for Ident

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl ToTokens for Ident

Source§

fn to_tokens(&self, tokens: &mut TokenStream)

Append self to the given TokenStream.
Source§

fn into_token_stream(self) -> TokenStream

Convert self directly into a TokenStream.
Source§

fn to_token_stream(&self) -> TokenStream

Convert self directly into a TokenStream.
Source§

impl ToTokens for Ident

Available on crate feature proc-macro2 only.
Source§

fn to_tokens(&self, tokens: &mut TokenStream2)

Write self to the given TokenStream. Read more
Source§

fn to_token_stream(&self) -> TokenStream2

Convert self directly into a TokenStream object. Read more
Source§

fn into_token_stream(self) -> TokenStream2

Convert self directly into a TokenStream object. Read more
Source§

impl Token for Ident

Source§

fn span(&self) -> &Span

Returns the span covered by this token.
Source§

impl Eq for Ident

Auto Trait Implementations§

§

impl Freeze for Ident

§

impl RefUnwindSafe for Ident

§

impl Send for Ident

§

impl Sync for Ident

§

impl Unpin for Ident

§

impl UnwindSafe for Ident

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.