Skip to content

Commit f8899d4

Browse files
author
ALisnevskiy
committed
add: call-by-reference
Signed-off-by: ALisnevskiy <[email protected]>
1 parent ee445a2 commit f8899d4

File tree

5 files changed

+133
-36
lines changed

5 files changed

+133
-36
lines changed

crates/core/src/ast.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,25 @@ pub struct VarDeclaration {
156156
pub init_value: Option<Box<Expr>>,
157157
}
158158

159+
#[derive(Debug, Clone)]
160+
pub enum ParamModifier {
161+
Const,
162+
Var,
163+
Out,
164+
}
165+
166+
#[derive(Debug, Clone)]
167+
pub struct Param {
168+
pub modifier: Option<ParamModifier>,
169+
pub ident: String,
170+
pub type_decl: Option<TypeDecl>,
171+
pub init_value: Option<Box<Expr>>
172+
}
173+
159174
#[derive(Debug, Clone)]
160175
pub struct ProcedureHeadDeclaration {
161176
pub name: String,
162-
pub params: Vec<(String, Option<TypeDecl>, Option<Box<Expr>>)>,
177+
pub params: Vec<Param>,
163178
pub return_type: Option<TypeDecl>,
164179
}
165180

crates/core/src/lexer.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub enum TokenType {
7575
Label,
7676
Object,
7777
Of,
78+
Out,
7879
Packed,
7980
Procedure,
8081
Program,
@@ -190,6 +191,7 @@ pub fn str_to_keyword(word: &str) -> Option<TokenType> {
190191
"object" => Some(TokenType::Object),
191192
"of" => Some(TokenType::Of),
192193
"or" => Some(TokenType::Or),
194+
"out" => Some(TokenType::Out),
193195
"packed" => Some(TokenType::Packed),
194196
"procedure" => Some(TokenType::Procedure),
195197
"program" => Some(TokenType::Program),

crates/core/src/parser.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
Block, CaseItem, CaseLabel, DeclSection, Designator, DesignatorItem, Expr,
44
ProcedureDeclaration, ProcedureHeadDeclaration, Program, Stmt,
55
TypeDeclaration, UnlabeledStmt, VarDeclaration, TypeDecl,
6+
ParamModifier, Param,
67
},
78
lexer::{SrcSpan, Token, TokenType},
89
};
@@ -451,32 +452,44 @@ where
451452
}
452453
}
453454

455+
fn parameter_modifier(&mut self) -> Option<ParamModifier> {
456+
match self.peek() {
457+
Some(Token { kind: TokenType::Const, .. }) => Some(ParamModifier::Const),
458+
Some(Token { kind: TokenType::Var, .. }) => Some(ParamModifier::Var),
459+
Some(Token { kind: TokenType::Out, .. }) => Some(ParamModifier::Out),
460+
Some(other) => None,
461+
None => None,
462+
}
463+
}
464+
454465
fn formal_parameter(
455466
&mut self
456-
) -> Result<Option<(String, Option<TypeDecl>, Option<Box<Expr>>)>, ParserError> {
457-
if let Some(parameter) = self.identifier() {
458-
let type_decl = self.type_decl()?;
459-
if let Some(token@Token { kind: TokenType::Assignment, .. }) = self.peek() {
467+
) -> Result<Option<Param>, ParserError> {
468+
let modifier = self.parameter_modifier();
469+
if let Some(ident) = self.identifier() {
470+
let mut param = Param {
471+
modifier,
472+
ident,
473+
type_decl: None,
474+
init_value: None,
475+
};
476+
if let Some(token@Token { kind: TokenType::Colon, .. }) = self.peek() {
460477
self.advance();
461-
if let Some(default_val) = self.expression()? {
462-
Ok(Some((parameter, type_decl, Some(Box::new(default_val)))))
463-
} else {
464-
Err(parser_error(
465-
ParserErrorType::ExpectedExpression,
466-
SrcSpan { start: token.start_pos, end: token.end_pos }
467-
))
468-
}
469-
} else {
470-
Ok(Some((parameter, type_decl, None)))
478+
param.type_decl = Some(self.expected_type_decl(&token)?);
479+
}
480+
if let Some(token@Token { kind: TokenType::Equal, .. }) = self.peek() {
481+
self.advance();
482+
param.init_value = Some(Box::new(self.expected_expression(&token)?));
471483
}
484+
Ok(Some(param))
472485
} else {
473486
Ok(None)
474487
}
475488
}
476489

477490
fn formal_parameter_list(
478491
&mut self
479-
) -> Result<Vec<(String, Option<TypeDecl>, Option<Box<Expr>>)>, ParserError> {
492+
) -> Result<Vec<Param>, ParserError> {
480493
let mut parameters = vec![];
481494
if let Some(parameter) = self.formal_parameter()? {
482495
parameters.push(parameter);
@@ -509,7 +522,6 @@ where
509522
mut head: ProcedureHeadDeclaration,
510523
prev_tok: &Token
511524
) -> Result<Option<ProcedureHeadDeclaration>, ParserError> {
512-
let mut return_type: Option<TypeDecl> = None;
513525
if let Some(ref colon_tok @ Token { kind: TokenType::Colon, .. }) = self.peek() {
514526
self.advance();
515527
head.return_type = Some(self.expected_type_decl(&colon_tok)?);
@@ -558,6 +570,7 @@ where
558570
fn proc_decl_section(&mut self) -> Result<Option<ProcedureDeclaration>, ParserError> {
559571
if let Some(head) = self.proc_decl_heading()? {
560572
if let Some(body) = self.compound_statement()? {
573+
self.consume(TokenType::Semicolon, SrcSpan { start: 0, end: 0 })?;
561574
Ok(Some(ProcedureDeclaration {
562575
head,
563576
body: Box::new(Stmt {

crates/jpci/src/callable.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ use core::ast::ProcedureDeclaration;
22

33
use crate::interpreter::{Interpreter, InterpreterError, Value};
44

5+
pub enum Arity {
6+
Static(usize),
7+
Var,
8+
}
9+
510
pub trait Callable {
611
fn call(
712
&mut self,
813
executor: &mut Interpreter,
914
args: Vec<Value>
1015
) -> Result<(), InterpreterError>;
11-
fn arity(&self) -> usize;
16+
fn arity(&self) -> Arity;
1217
}
1318

1419
#[derive(Debug, Clone)]
@@ -36,7 +41,7 @@ impl Callable for WriteProcedureValue {
3641
Ok(())
3742
}
3843

39-
fn arity(&self) -> usize { 1 }
44+
fn arity(&self) -> Arity { Arity::Var }
4045
}
4146

4247
#[derive(Debug, Clone)]
@@ -59,7 +64,7 @@ impl Callable for WritelnProcedureValue {
5964
Ok(())
6065
}
6166

62-
fn arity(&self) -> usize { 1 }
67+
fn arity(&self) -> Arity { Arity::Var }
6368
}
6469

6570

@@ -69,13 +74,36 @@ pub struct ReadProcedureValue;
6974
impl Callable for ReadProcedureValue {
7075
fn call(
7176
&mut self,
72-
_executor: &mut Interpreter,
73-
_args: Vec<Value>
77+
executor: &mut Interpreter,
78+
args: Vec<Value>
7479
) -> Result<(), InterpreterError> {
80+
let mut buffer = String::new();
81+
for arg in args.into_iter() {
82+
match arg {
83+
Value::Ref(designator) => {
84+
std::io::stdin().read_line(&mut buffer).unwrap();
85+
// TODO: Handle arrays, class fields, etc..
86+
match executor.environment.get_value(&designator.name) {
87+
Some(Value::UnsignedInteger(_)) => {
88+
match buffer.trim().parse::<i64>() {
89+
Ok(num) => {
90+
let val = Value::UnsignedInteger(num);
91+
executor.environment.assign(&designator.name, val).unwrap();
92+
},
93+
Err(_) => panic!("Failed to parse"),
94+
}
95+
},
96+
Some(_) => panic!("Not implemented"),
97+
None => panic!("No such variable"),
98+
}
99+
},
100+
_ => panic!("Read accept only call-by-reference parameters"),
101+
}
102+
}
75103
Ok(())
76104
}
77105

78-
fn arity(&self) -> usize { 0 }
106+
fn arity(&self) -> Arity { Arity::Static(1) }
79107
}
80108

81109
#[derive(Debug, Clone)]
@@ -90,7 +118,7 @@ impl Callable for ReadlnProcedureValue {
90118
Ok(())
91119
}
92120

93-
fn arity(&self) -> usize { 0 }
121+
fn arity(&self) -> Arity { Arity::Static(1) }
94122
}
95123

96124
impl Callable for NativeProcedureValue {
@@ -103,14 +131,14 @@ impl Callable for NativeProcedureValue {
103131
let def = &self.decl;
104132
let head = &def.head;
105133
for (param, value) in head.params.iter().zip(args.into_iter()) {
106-
executor.environment.define(&param.0, value)?;
134+
executor.environment.define(&param.ident, value)?;
107135
}
108136
executor.visit_statement(&def.body)?;
109137
executor.scope_exit()?;
110138
Ok(())
111139
}
112140

113-
fn arity(&self) -> usize { self.decl.head.params.len() }
141+
fn arity(&self) -> Arity { Arity::Static(self.decl.head.params.len()) }
114142
}
115143

116144
#[derive(Debug, Clone)]
@@ -123,7 +151,7 @@ pub enum ProcedureValue {
123151
}
124152

125153
impl Callable for ProcedureValue {
126-
fn arity(&self) -> usize {
154+
fn arity(&self) -> Arity {
127155
match self {
128156
ProcedureValue::Native(ref value) => value.arity(),
129157
ProcedureValue::Write(ref value) => value.arity(),

crates/jpci/src/interpreter.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ use std::{collections::HashMap, fmt::{self, Debug}, fs};
22

33
use core::{
44
ast::{
5-
Block, DeclSection, DesignatorItem, Expr, ProcedureDeclaration,
5+
Block, DeclSection, Designator, DesignatorItem, Expr, ProcedureDeclaration,
66
Program, Stmt, TypeDeclaration, UnlabeledStmt, VarDeclaration,
77
}, error::{self, Error}, lexer::{self, Lexer}, parser::Parser,
88
};
99

1010
use camino::Utf8PathBuf;
1111

1212
use crate::callable::{
13+
Arity,
1314
Callable, NativeProcedureValue, ProcedureValue, ReadProcedureValue,
14-
ReadlnProcedureValue, WriteProcedureValue, WritelnProcedureValue
15+
ReadlnProcedureValue, WriteProcedureValue, WritelnProcedureValue,
1516
};
1617

1718
#[derive(Debug, Clone)]
@@ -34,6 +35,8 @@ pub enum Value {
3435
String(String),
3536
Boolean(bool),
3637
Procedure(ProcedureValue),
38+
// TODO: When classes arive, change to some reference type
39+
Ref(Designator),
3740
Null,
3841
}
3942

@@ -45,6 +48,7 @@ impl fmt::Display for Value {
4548
Value::String(s) => write!(f, "\"{:?}\"", s),
4649
Value::Boolean(b) => write!(f, "{:?}", b),
4750
Value::Procedure(p) => write!(f, "{:?}", p),
51+
Value::Ref(d) => write!(f, "{:?}", d),
4852
Value::Null => write!(f, "null"),
4953
}
5054
}
@@ -244,18 +248,29 @@ impl Interpreter {
244248
);
245249
match designator.items.first() {
246250
Some(&DesignatorItem::Call { ref arguments }) => {
247-
if arguments.len() != proc.arity() {
248-
return Err(InterpreterError::MismathedArgumentsCount);
251+
if let Arity::Static(arity) = proc.arity() {
252+
if arity != arguments.len() {
253+
return Err(InterpreterError::MismathedArgumentsCount);
254+
}
249255
}
250-
let values: Result<Vec<_>, _> = arguments.iter()
251-
.map(|arg| self.visit_expr(&arg.0))
256+
let values: Result<Vec<Value>, _> = arguments.iter()
257+
.map(|arg| match *arg.0 {
258+
// Call-by-reference
259+
// TODO: check if formal parameter has 'var' modifier
260+
Expr::Designator { ref designator } => Ok(Value::Ref(designator.clone())),
261+
// Call-by-value
262+
// TODO: wtf boxing???
263+
ref expr => self.visit_expr(&Box::new(expr.clone())),
264+
})
252265
.collect();
253266
proc.call(self, values?)?;
254267
Ok(())
255268
},
256269
None => {
257-
if proc.arity() != 0 {
258-
return Err(InterpreterError::MismathedArgumentsCount);
270+
if let Arity::Static(arity) = proc.arity() {
271+
if arity != 0 {
272+
return Err(InterpreterError::MismathedArgumentsCount);
273+
}
259274
}
260275
proc.call(self, vec![])?;
261276
Ok(())
@@ -312,7 +327,9 @@ impl Interpreter {
312327
loop {
313328
match self.visit_expr(condition)? {
314329
Value::Boolean(false) => break,
315-
Value::Boolean(true) => self.visit_statement(statement)?,
330+
Value::Boolean(true) => {
331+
self.visit_statement(statement)?
332+
},
316333
_ => return Err(InterpreterError::MismatchedTypes),
317334
}
318335
}
@@ -365,13 +382,35 @@ impl Interpreter {
365382
Expr::Binary { left, operator, right } => {
366383
let left = self.visit_expr(left)?;
367384
let right = self.visit_expr(right)?;
385+
if operator.kind == lexer::TokenType::Or {
386+
return match (left, right) {
387+
(Value::Boolean(a), Value::Boolean(b)) => {
388+
Ok(Value::Boolean(a | b))
389+
},
390+
_ => Err(InterpreterError::NotImplemented),
391+
}
392+
}
393+
if operator.kind == lexer::TokenType::And {
394+
return match (left, right) {
395+
(Value::Boolean(a), Value::Boolean(b)) => {
396+
Ok(Value::Boolean(a & b))
397+
},
398+
_ => Err(InterpreterError::NotImplemented),
399+
}
400+
}
368401
match (left, right) {
369402
(Value::UnsignedInteger(a), Value::UnsignedInteger(b)) => {
370403
match operator.kind {
371404
lexer::TokenType::Plus => Ok(Value::UnsignedInteger(a + b)),
372405
lexer::TokenType::Minus => Ok(Value::UnsignedInteger(a - b)),
373406
lexer::TokenType::Star => Ok(Value::UnsignedInteger(a * b)),
374407
lexer::TokenType::Slash => Ok(Value::UnsignedInteger(a / b)),
408+
lexer::TokenType::Greater => Ok(Value::Boolean(a > b)),
409+
lexer::TokenType::GreaterEqual => Ok(Value::Boolean(a >= b)),
410+
lexer::TokenType::Less => Ok(Value::Boolean(a < b)),
411+
lexer::TokenType::LessEqual => Ok(Value::Boolean(a <= b)),
412+
lexer::TokenType::Equal => Ok(Value::Boolean(a == b)),
413+
lexer::TokenType::NotEqual => Ok(Value::Boolean(a != b)),
375414
_ => Err(InterpreterError::NotImplemented),
376415
}
377416
},

0 commit comments

Comments
 (0)