Skip to content

Commit

Permalink
Added initial support for static variables.
Browse files Browse the repository at this point in the history
They still have global scoping even inside functions
  • Loading branch information
SKyletoft committed Feb 26, 2021
1 parent 91113dc commit 5882bb8
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 32 deletions.
38 changes: 31 additions & 7 deletions src/compile_flisp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ use crate::*;
///Technically illegal address for use in register -> register transfers
const ABOVE_STACK_OFFSET: isize = -1;

///Name (lifetime from source code), (Type, Stack position (from the bottom))
type Variables<'a, 'b> = &'b mut HashMap<&'a str, (Type, isize)>;

///Name (lifetime from source code), Type
type GlobalVariables<'a, 'b> = &'b mut HashMap<&'a str, Type>;

///Name, Argument list (not named)
type Functions<'a, 'b> = &'b mut HashMap<&'a str, &'a [Variable<'a>]>;

#[derive(Debug, PartialEq)]
struct State<'a, 'b, 'c, 'd, 'e, 'f> {
variables: &'b mut HashMap<&'a str, (Type, isize)>,
global_variables: &'c mut HashMap<&'a str, Type>,
functions: &'d mut HashMap<&'a str, &'a [Variable<'a>]>,
variables: Variables<'a, 'b>,
global_variables: GlobalVariables<'a, 'c>,
functions: Functions<'a, 'd>,
stack_size: &'f mut isize,
scope_name: &'e str,
line_id: usize,
Expand Down Expand Up @@ -66,8 +75,15 @@ fn compile_element<'a>(
optimise: bool,
) -> Result<Vec<CommentedInstruction<'a>>, CompileError> {
let res = match element {
LanguageElement::VariableDeclaration { typ, name } => {
if state.scope_name == "global" {
LanguageElement::VariableDeclaration {
typ,
name,
is_static,
} => {
if state.scope_name == "global" || *is_static {
if state.scope_name == "global" && !is_static {
return Err(CompileError(line!(), "Nonstatic global variable!"));
}
if state.global_variables.contains_key(name) {
dbg!(element);
return Err(CompileError(line!(), "Name already exists in scope!"));
Expand Down Expand Up @@ -108,7 +124,12 @@ fn compile_element<'a>(
statement
}

LanguageElement::VariableDeclarationAssignment { typ, name, value } => {
LanguageElement::VariableDeclarationAssignment {
typ,
name,
value,
is_static,
} => {
let global_def = |val: &StatementElement| match val {
StatementElement::Num(n) => Ok(*n),
StatementElement::Char(c) => Ok(*c as isize),
Expand All @@ -118,7 +139,10 @@ fn compile_element<'a>(
"Non constant in array initialisation",
)),
};
if state.scope_name == "global" {
if state.scope_name == "global" || *is_static {
if state.scope_name == "global" && !is_static {
return Err(CompileError(line!(), "Nonstatic global variable!"));
}
if state.global_variables.contains_key(name) {
dbg!(element);
return Err(CompileError(line!(), "Name already exists in scope!"));
Expand Down
22 changes: 5 additions & 17 deletions src/flisp_instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl fmt::Display for Instruction {
Instruction::TSTA => write!(f, "\tTSTA\t"),
Instruction::COMA => write!(f, "\tCOMA\t"),
Instruction::RTS => write!(f, "\tRTS\t"),
Instruction::Label(l) => write!(f, "{}", l),
Instruction::Label(l) => write!(f, "{}", l.strip_prefix("global::").unwrap_or(l)),
Instruction::FCB(bytes) => {
//Maybe insert a newline every eight values?
write!(f, "\tFCB\t")?;
Expand Down Expand Up @@ -126,23 +126,14 @@ impl fmt::UpperHex for Instruction {
Instruction::DEC(a) => write!(f, "\tDEC\t{:X}", *a),
Instruction::LSL(a) => write!(f, "\rLSL\t{:X}", *a),
Instruction::LSR(a) => write!(f, "\tLSR\t{:X}", *a),
Instruction::LSLA => write!(f, "\tLSLA\t"),
Instruction::LSRA => write!(f, "\tLSRA\t"),
Instruction::INCA => write!(f, "\tINCA\t"),
Instruction::DECA => write!(f, "\tDECA\t"),
Instruction::PSHA => write!(f, "\tPSHA\t"),
Instruction::PULA => write!(f, "\tPULA\t"),
Instruction::TSTA => write!(f, "\tTSTA\t"),
Instruction::COMA => write!(f, "\tCOMA\t"),
Instruction::RTS => write!(f, "\tRTS\t"),
Instruction::Label(l) => write!(f, "{}", l),
Instruction::FCB(bytes) => {
write!(f, "\tFCB\t")?;
for &val in bytes.iter().take(bytes.len() - 1) {
write!(f, "${:02X},", val % 256)?;
}
write!(f, "${:02X}", bytes[bytes.len() - 1])
}
instruction => write!(f, "{}", instruction),
}
}
}
Expand Down Expand Up @@ -310,8 +301,8 @@ impl fmt::Display for Addressing {
Addressing::SP(d) => write!(f, "{:03},SP", *d % 256),
Addressing::Xn(d) => write!(f, "{:03},X", *d % 256),
Addressing::Yn(d) => write!(f, "{:03},Y", *d % 256),
Addressing::Label(l) => write!(f, "{}", l),
Addressing::DataLabel(l) => write!(f, "#{}", l),
Addressing::Label(l) => write!(f, "{}", l.strip_prefix("global::").unwrap_or(l)),
Addressing::DataLabel(l) => write!(f, "#{}", l.strip_prefix("global::").unwrap_or(l)),
Addressing::AX => write!(f, "A,X"),
Addressing::AY => write!(f, "A,Y"),
}
Expand All @@ -326,10 +317,7 @@ impl fmt::UpperHex for Addressing {
Addressing::SP(d) => write!(f, "${:02X},SP", *d as u8),
Addressing::Xn(d) => write!(f, "${:02X},X", *d as u8),
Addressing::Yn(d) => write!(f, "${:02X},Y", *d as u8),
Addressing::Label(l) => write!(f, "{}", l),
Addressing::DataLabel(l) => write!(f, "#{}", l),
Addressing::AX => write!(f, "A,X"),
Addressing::AY => write!(f, "A,Y"),
adr => write!(f, "{}", adr),
}
}
}
2 changes: 2 additions & 0 deletions src/language_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub(crate) enum LanguageElement<'a> {
VariableDeclaration {
typ: Type,
name: &'a str,
is_static: bool,
},
VariableAssignment {
name: &'a str,
Expand All @@ -18,6 +19,7 @@ pub(crate) enum LanguageElement<'a> {
typ: Type,
name: &'a str,
value: StatementElement<'a>,
is_static: bool,
},
PointerAssignment {
ptr: StatementElement<'a>,
Expand Down
62 changes: 60 additions & 2 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,33 @@ fn construct_structure_from_tokens<'a>(
typ,
name,
value: rhs_parsed,
is_static: false,
}
}

//Static pointer variable declaration
[Static, Decl(t), Deref(d), Assign, ..] => {
let mut typ = Type::Ptr(Box::new(t.clone()));
let mut r = d.as_ref();
let name;
while let [Deref(b)] = r.as_ref() {
typ = Type::Ptr(Box::new(typ));
r = b;
}
if let [Token::Name(n)] = r {
name = *n;
} else {
dbg!(tokens);
return Err(ParseError(line!(), "Couldn't parse name/pointer type"));
}
let rhs = &tokens[4..];
let rhs_verified = StatementToken::from_tokens(rhs)?;
let rhs_parsed = StatementElement::from_tokens(rhs_verified)?;
LanguageElement::VariableDeclarationAssignment {
typ,
name,
value: rhs_parsed,
is_static: true,
}
}

Expand All @@ -80,6 +107,20 @@ fn construct_structure_from_tokens<'a>(
typ: t.clone(),
name: *n,
value: rhs_parsed,
is_static: false,
}
}

//Static variable declaration
[Static, Decl(t), Token::Name(n), Assign, ..] => {
let rhs = &tokens[4..];
let rhs_verified = StatementToken::from_tokens(rhs)?;
let rhs_parsed = StatementElement::from_tokens(rhs_verified)?;
LanguageElement::VariableDeclarationAssignment {
typ: t.clone(),
name: *n,
value: rhs_parsed,
is_static: true,
}
}

Expand Down Expand Up @@ -110,6 +151,14 @@ fn construct_structure_from_tokens<'a>(
[Decl(t), Token::Name(n)] => LanguageElement::VariableDeclaration {
typ: t.clone(),
name: *n,
is_static: false,
},

//Static variable declaration (without init)
[Static, Decl(t), Token::Name(n)] => LanguageElement::VariableDeclaration {
typ: t.clone(),
name: *n,
is_static: true,
},

//If else if
Expand Down Expand Up @@ -231,7 +280,11 @@ pub(crate) fn type_check(

for line in block {
match line {
LanguageElement::VariableDeclaration { typ, name } => variables.push(Variable {
LanguageElement::VariableDeclaration {
typ,
name,
is_static: _,
} => variables.push(Variable {
typ: typ.clone(),
name: *name,
}),
Expand All @@ -242,7 +295,12 @@ pub(crate) fn type_check(
}
}

LanguageElement::VariableDeclarationAssignment { typ, name, value } => {
LanguageElement::VariableDeclarationAssignment {
typ,
name,
value,
is_static: _,
} => {
variables.push(Variable {
typ: typ.clone(),
name: *name,
Expand Down
24 changes: 21 additions & 3 deletions src/statement_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,21 +595,39 @@ fn do_operation<'a>(
pub(crate) fn move_declarations_first(block: &mut Block) {
let give_value = |element: &LanguageElement| -> usize {
match element {
LanguageElement::VariableDeclaration { typ: _, name: _ } => 0,
LanguageElement::VariableDeclaration {
typ: _,
name: _,
is_static: true,
} => 0,

LanguageElement::VariableDeclarationAssignment {
typ: _,
name: _,
value: _,
is_static: true,
} => 0,

LanguageElement::VariableDeclaration {
typ: _,
name: _,
is_static: false,
} => 1,

LanguageElement::VariableDeclarationAssignment {
typ: _,
name: _,
value: _,
is_static: false,
} => 1,

LanguageElement::FunctionDeclaration {
typ: _,
name: _,
args: _,
block: _,
} => 0,
_ => 1,
} => 2,
_ => 3,
}
};
block.sort_by_key(give_value);
Expand Down
7 changes: 4 additions & 3 deletions tests/test23.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
int foo = 54;
static int foo = 54;

***foo = 56;
*58 = ****foo;
int main() {
static int bar = 432;
}
1 change: 1 addition & 0 deletions todo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Change all `'a str`s to `Cow<String>`s

0 comments on commit 5882bb8

Please sign in to comment.