Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
gpoblon committed Sep 21, 2020
1 parent 36e7105 commit 9c029e3
Show file tree
Hide file tree
Showing 27 changed files with 1,203 additions and 614 deletions.
312 changes: 199 additions & 113 deletions rudder-lang/docs/usage.adoc

Large diffs are not rendered by default.

54 changes: 21 additions & 33 deletions rudder-lang/src/bin/rudderc.rs
Expand Up @@ -14,19 +14,18 @@
//!
//! 3- ncf library -> generate_lib() -> resourcelib.rl + translate-config

use colored::Colorize;
// imports log macros;
use log::*;
use std::process::exit;
use structopt::StructOpt;

use rudderc::{
compile::compile_file,
compile::compile,
error::Error,
migrate::migrate,
opt::Opt,
technique::{generate_technique, read_technique},
Action, ActionResult,
technique::{technique_generate, technique_read},
Action,
};

// MAIN
Expand Down Expand Up @@ -66,62 +65,51 @@ use rudderc::{
fn main() {
let command = Opt::from_args();
let (output, log_level, has_backtrace) = command.extract_logging_infos();
let action = command.to_action();
// Initialize logger
let action = command.as_action();
// Initialize logger and output
output.init(log_level, action, has_backtrace);

let ctx = command.extract_parameters().unwrap_or_else(|e| {
error!("{}", e);
// required before returning in order to have proper logging
output.print(
action,
"input not set",
Err(Error::new("Not set yet".to_owned())),
"Input not set".to_owned(),
Err(Error::new(
"Could not determine proper I/O from given parameters".to_owned(),
)),
);
exit(1);
});

info!("I/O context: {}", ctx);

// Actual action
// read = rl -> json
// migrate = cf -> rl
// compile = rl -> cf / dsc
// generate = json -> rl / cf / dsc
// TODO make the right calls
// generate = json -> json { rl + cf + dsc }
// TODO collect logs in ram rather than directly printing it
let action_result = match action {
Action::Compile => compile_file(&ctx, true),
Action::Compile => compile(&ctx, true),
// TODO Migrate: call cf_to_json perl script then call json->rl == Technique generate()
Action::Migrate => migrate(&ctx),
// TODO: rl -> json + add a json wrapper : { data: {}, errors: {}}
Action::ReadTechnique => read_technique(&ctx),
Action::ReadTechnique => technique_read(&ctx),
// TODO Generate: call technique generate then compile into all formats + json wrapper: { rl: "", dsc: "", cf: "", errors:{} }
Action::GenerateTechnique => generate_technique(&ctx),
Action::GenerateTechnique => technique_generate(&ctx),
};
// these logs should disappear since output will take care of it (to only print json or in terminal, not a mix)
// match &action_result {
// Ok(_) => info!(
// "{} {}",
// format!("{:?}", action).bright_green(),
// "OK".bright_cyan()
// ),
// Err(e) => error!("{}", e),
// };
let action_status = action_result.is_ok();
output.print(action, ctx.input.display(), action_result);
output.print(
action,
match &ctx.input {
Some(path) => path.to_string_lossy().to_string(),
None => "STDIN".to_owned(),
},
action_result,
);
if action_status {
exit(1)
}
}

// prévu refonte cli + tests dsc
// en pratique la refonte cli a soulevé pas mal de questions:
// passer de : créer un fichier dans un format particulier dans un fichier
// à : 4 actions possibles, peut generer +rs formats dans un json wrappé, qui contient possiblement les logs (qui sont mal formattés actuellement), ou des fichiers directement etc
// -> impl action system
// lié à çá le souci de logs

// Phase 2
// - function, measure(=fact), action
// - variable = anything
Expand Down
82 changes: 58 additions & 24 deletions rudder-lang/src/compile.rs
Expand Up @@ -12,30 +12,54 @@ use crate::{
ActionResult,
};
use colored::Colorize;
use std::{fs, path::Path};
use std::{
fs,
io::Read,
path::{Path, PathBuf},
};
use typed_arena::Arena;

/// Add a single file content to the sources and parse it
pub fn parse_file<'src>(
past: &mut PAST<'src>,
sources: &'src Arena<String>,
path: &Path,
path: &Option<PathBuf>,
) -> Result<()> {
let filename = sources.alloc(match path.file_name() {
Some(file) => file.to_string_lossy().to_string(),
None => return Err(Error::new(format!("{:?} should be a .rl file", path))),
});
info!(
"|- {} {}",
"Parsing".bright_green(),
filename.bright_yellow()
);
match fs::read_to_string(path) {
Ok(content) => {
let content_str = sources.alloc(content);
past.add_file(filename, content_str)
match path {
Some(file_path) => {
let filename = sources.alloc(match file_path.file_name() {
Some(file) => file.to_string_lossy().into(),
None => return Err(Error::new(format!("{:?} should be a .rl file", path))),
});
info!(
"|- {} {}",
"Parsing".bright_green(),
filename.bright_yellow()
);
match fs::read_to_string(file_path) {
Ok(content) => {
let content_str = sources.alloc(content);
past.add_file(filename, content_str)
}
Err(e) => Err(err!(Token::new(filename, ""), "{}", e)),
}
}
None => {
sources.alloc("STDIN".to_owned());
info!(
"|- {} {}",
"Parsing".bright_green(),
"STDIN".bright_yellow()
);
let mut buffer = String::new();
match std::io::stdin().read_to_string(&mut buffer) {
Ok(content) => {
let content_str = sources.alloc(buffer);
past.add_file("STDIN", content_str)
}
Err(e) => Err(err!(Token::new("STDIN", ""), "{}", e)),
}
}
Err(e) => Err(err!(Token::new(filename, ""), "{}", e)),
}
}

Expand All @@ -48,10 +72,13 @@ pub fn technique_to_ir<'src>(

// read and add files
info!(
"{} of {} into {}",
"{} of {}",
"Processing compilation".bright_green(),
ctx.input.to_string_lossy().bright_yellow(),
ctx.output.to_string_lossy().bright_yellow()
match &ctx.input {
Some(input) => input.to_string_lossy(),
None => "STDIN".into(),
}
.bright_yellow(),
);

parse_file(&mut past, &sources, &ctx.input)?;
Expand All @@ -68,20 +95,27 @@ pub fn technique_to_ir<'src>(
}

/// Compile a file from rudder-lang to cfengine / dsc / json
pub fn compile_file(ctx: &IOContext, technique: bool) -> Result<Vec<ActionResult>> {
pub fn compile(ctx: &IOContext, technique: bool) -> Result<Vec<ActionResult>> {
let sources = Arena::new();
let ir = technique_to_ir(ctx, &sources)?;

// generate final output
info!("|- {}", "Generating output code".bright_green());
let input = match &ctx.input {
Some(i) => Some(i.as_path()),
None => None,
};
let output = match &ctx.output {
Some(o) => Some(o.as_path()),
None => None,
};

let (input_file, output_file) = if technique {
// TODO this should be a technique name not a file name
(Some(ctx.input.as_path()), Some(ctx.output.as_path()))
(input, output)
} else {
(None, None)
};
let mut generator = new_generator(&ctx.format)?;
generator.generate(&ir, input_file, output_file, technique)?;
// TODO fill action result directly
Ok(vec![ActionResult::default()])
generator.generate(&ir, input_file, output_file, technique)
}
2 changes: 1 addition & 1 deletion rudder-lang/src/error.rs
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2019-2020 Normation SAS

use crate::logger::Backtrace;
/// We write our own error type to have a consistent error type through all our code.
/// We translate other types to this one when necessary.
/// All case contain 4 elements:
Expand All @@ -12,6 +11,7 @@ use crate::logger::Backtrace;
/// - Compilation error: usually we can skip what we are doing and go to next iteration
/// - List: aggregate compilation errors so that user can fix them all ant once
///
use crate::output::Backtrace;
use crate::parser::Token;
use colored::Colorize;
use ngrammatic::CorpusBuilder;
Expand Down
4 changes: 2 additions & 2 deletions rudder-lang/src/generator.rs
Expand Up @@ -7,7 +7,7 @@ pub mod json;
pub mod markdown;

pub use self::{cfengine::CFEngine, dsc::DSC, json::JSON, markdown::Markdown};
use crate::{error::*, ir::ir2::IR2};
use crate::{error::*, ir::ir2::IR2, ActionResult};
use serde::{Deserialize, Deserializer, Serialize};
use std::{fmt, path::Path, str::FromStr};

Expand All @@ -22,7 +22,7 @@ pub trait Generator {
source_file: Option<&Path>,
dest_file: Option<&Path>,
technique_metadata: bool,
) -> Result<()>;
) -> Result<Vec<ActionResult>>;
}

pub fn new_generator(format: &Format) -> Result<Box<dyn Generator>> {
Expand Down
36 changes: 16 additions & 20 deletions rudder-lang/src/generator/cfengine.rs
Expand Up @@ -3,12 +3,13 @@

use super::Generator;
use crate::{
ir::{enums::EnumExpressionPart, resource::*, value::*, ir2::IR2},
error::*,
generator::cfengine::syntax::{quoted, Bundle, Method, Policy, Promise},
ir::{enums::EnumExpressionPart, ir2::IR2, resource::*, value::*},
parser::*,
ActionResult, Format,
};
use std::{collections::HashMap, ffi::OsStr, fs::File, io::Write, path::Path};
use std::{collections::HashMap, ffi::OsStr, path::Path};
use toml::Value as TomlValue;

mod syntax;
Expand Down Expand Up @@ -279,8 +280,8 @@ impl Generator for CFEngine {
source_file: Option<&Path>,
dest_file: Option<&Path>,
policy_metadata: bool,
) -> Result<()> {
let mut files: HashMap<String, String> = HashMap::new();
) -> Result<Vec<ActionResult>> {
let mut files: Vec<ActionResult> = Vec::new();
// TODO add global variable definitions
for (resource_name, resource) in gc.resources.iter() {
for (state_name, state) in resource.states.iter() {
Expand Down Expand Up @@ -343,27 +344,22 @@ impl Generator for CFEngine {
.name(extract("name"))
.version(extract("version"))
.bundle(bundle);
files.insert(file_to_create, policy.to_string());
files.push(ActionResult::new(
Format::CFEngine,
Some(file_to_create.into()),
Some(policy.to_string()),
));
} else {
files.insert(file_to_create, bundle.to_string());
files.push(ActionResult::new(
Format::CFEngine,
Some(file_to_create.into()),
Some(bundle.to_string()),
));
}
}
}
// create file if needed
if files.is_empty() {
match dest_file {
Some(filename) => File::create(filename).expect("Could not create output file"),
None => return Err(Error::new("No file to create".to_owned())),
};
}

// write to file
for (name, content) in files.iter() {
let mut file = File::create(name).expect("Could not create output file");
file.write_all(content.as_bytes())
.expect("Could not write content into output file");
}
Ok(())
Ok(files)
}
}

Expand Down

0 comments on commit 9c029e3

Please sign in to comment.