Skip to content

Instantly share code, notes, and snippets.

@JeanRibes
Created November 10, 2021 23:54
Show Gist options
  • Save JeanRibes/7f2e973f96667427d95b945454d3ed48 to your computer and use it in GitHub Desktop.
Save JeanRibes/7f2e973f96667427d95b945454d3ed48 to your computer and use it in GitHub Desktop.
compilateur LOGO en rust, sortie SVG dans le terminal
use std::ops::Add;
use std::borrow::Borrow;
use crate::Instruction::{Forward, Left, Right, Repeat};
use std::panic::panic_any;
use std::f64::consts::PI;
use std::fs::File;
use std::io::Write;
#[derive(Clone)]
enum Instruction {
Forward(u8),
Left(u8),
Right(u8),
Repeat(u8, Vec<Instruction>),
}
#[derive(Clone)]
struct Crayon {
x: f64,
y: f64,
t: f64,
}
#[derive(Clone)]
enum Point {
Point(f64, f64)
}
fn ins_to_str(ins: Instruction) -> String {
return match ins {
Forward(x) => format!("Forward {}", x).to_string(),
Left(x) => format!("Left {}", x).to_string(),
Right(x) => format!("Right {}", x).to_string(),
Repeat(repeat, prgm) => {
let mut res = format!("Repeat {} [", repeat).to_string();
for subi in prgm {
res += ins_to_str(subi).as_str();
res += ", ";
}
return res + "]";
}
};
}
fn print_instructions(prgm: Vec<Instruction>) {
println!("{}", ins_to_str(Repeat(1, prgm)));
}
fn flatten(prgm_in: Vec<Instruction>, mut prgm_out: Vec<Instruction>) -> Vec<Instruction> {
for ins in prgm_in {
match ins {
Repeat(repeat, sub_prgm) => {
for i in (0..repeat) {
prgm_out = flatten(Vec::from(sub_prgm.borrow()), prgm_out);
}
}
_ => {
prgm_out.push(ins.clone());
}
}
}
return prgm_out;
}
fn draw_ins(mut crayon: Crayon, ins: Instruction) -> Crayon {
match ins {
Forward(l) => {
crayon.x += f64::from(l) * crayon.t.cos();
crayon.y += f64::from(l) * crayon.t.sin();
}
Left(t) => {
crayon.t -= f64::from(t) * PI / f64::from(180);
}
Right(t) => {
crayon.t += f64::from(t) * PI / f64::from(180);
}
Repeat(_, _) => {
panic_any("flatten() forgotten");
}
}
return crayon;
}
fn turle(prgm: Vec<Instruction>) -> Vec<Point> {
let mut crayon = Crayon {
x: 150.0,
y: 150.0,
t: 0.0,
};
let mut coords: Vec<Point> = Vec::new();
for ins in prgm {
crayon = draw_ins(crayon, ins);
coords.push(Point::Point(crayon.x, crayon.y));
}
return coords;
}
fn main() {
/*let prgm = vec![Forward(10), Left(90), Forward(10),
Repeat(2, vec![Forward(20), Right(10)])];*/
// [ Repeat 36 [ Right 10, Repeat 8 [ Forward 25, Left 45 ] ]]
let prgm = vec![Repeat(36, vec![Right(10),Repeat(8,vec![Forward(25), Left(45)])])];
//print_instructions(Vec::from(prgm.borrow()));
let mut flattened = Vec::new();
flattened = flatten(prgm, flattened);
//print_instructions(flattened.clone());
let coords = turle(flattened);
/*for Point::Point(x, y) in Vec::from(coords.borrow()) {
println!("{} {}", x, y)
}*/
let mut file = match File::open("./logo.svg") {
Err(why) => panic!("couldn't open file: {}", why),
Ok(file) => file,
};
println!("<?xml version=\"1.0\" encoding=\"utf-8\"?><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"300\" height=\"300\">\n<title>SVG Jean et El Hadj</title>");
let mut x0: f64 = 150 as f64;
let mut y0: f64 = 150 as f64;
for Point::Point(x, y) in coords {
println!("<line x1=\"{}\" y1=\"{}\" x2=\"{}\" y2=\"{}\" stroke=\"red\" stroke-width=\"1\" />", x0, y0, x, y);
x0=x;
y0=y;
}
println!("</svg>");
file.flush();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment