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
impl Ident
Sourcepub const fn string(&self) -> &String
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
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 }
Sourcepub const fn new(string: String, span: Span) -> Ident
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 Ord for Ident
impl Ord for Ident
Source§impl PartialOrd for Ident
impl PartialOrd for Ident
Source§impl ToTokens for Ident
impl ToTokens for Ident
Source§fn to_tokens(&self, tokens: &mut TokenStream)
fn to_tokens(&self, tokens: &mut TokenStream)
Append
self
to the given TokenStream
.Source§fn into_token_stream(self) -> TokenStream
fn into_token_stream(self) -> TokenStream
Convert
self
directly into a TokenStream
.Source§fn to_token_stream(&self) -> TokenStream
fn to_token_stream(&self) -> TokenStream
Convert
self
directly into a TokenStream
.Source§impl ToTokens for Ident
Available on crate feature proc-macro2
only.
impl ToTokens for Ident
Available on crate feature
proc-macro2
only.Source§fn to_tokens(&self, tokens: &mut TokenStream2)
fn to_tokens(&self, tokens: &mut TokenStream2)
Source§fn to_token_stream(&self) -> TokenStream2
fn to_token_stream(&self) -> TokenStream2
Source§fn into_token_stream(self) -> TokenStream2
fn into_token_stream(self) -> TokenStream2
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more