1 package org.simantics.scl.compiler.elaboration.java;
3 import org.cojen.classfile.TypeDesc;
4 import org.osgi.service.component.annotations.Component;
5 import org.simantics.scl.compiler.commands.CommandSession;
6 import org.simantics.scl.compiler.common.names.Name;
7 import org.simantics.scl.compiler.constants.JavaMethod;
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
9 import org.simantics.scl.compiler.elaboration.expressions.EApply;
10 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
11 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
12 import org.simantics.scl.compiler.elaboration.expressions.Expression;
13 import org.simantics.scl.compiler.elaboration.macros.MacroRule;
14 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
15 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
16 import org.simantics.scl.compiler.module.ConcreteModule;
17 import org.simantics.scl.compiler.types.TCon;
18 import org.simantics.scl.compiler.types.Type;
19 import org.simantics.scl.compiler.types.Types;
20 import org.simantics.scl.compiler.types.kinds.Kinds;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import org.slf4j.Marker;
26 public class LoggingModule extends ConcreteModule {
28 private static final String[] LOGGING_METHODS = new String[] {
29 "trace", "debug", "info", "warn", "error"
32 public static final TCon Throwable = Types.con("Prelude", "Throwable");
34 public LoggingModule() {
38 TCon Logger = Types.con(getName(), "Logger");
39 StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
40 loggerConstructor.external = true;
41 addTypeDescriptor("Logger", loggerConstructor);
44 TCon Marker = Types.con(getName(), "Marker");
45 StandardTypeConstructor markerConstructor = new StandardTypeConstructor(Marker, Kinds.STAR, TypeDesc.forClass(Marker.class));
46 markerConstructor.external = true;
47 addTypeDescriptor("Marker", markerConstructor);
50 Type isEnabledType = Types.functionE(Types.PUNIT, Types.PROC, Types.BOOLEAN);
51 Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
52 Type loggingTypeWithMarker = Types.functionE(new Type[] { Marker, Types.STRING }, Types.PROC, Types.UNIT);
53 Type loggingTypeWithException = Types.functionE(new Type[] { Types.STRING, Throwable }, Types.PROC, Types.UNIT);
54 Type loggingTypeWithMarkerAndException = Types.functionE(new Type[] { Marker, Types.STRING, Throwable }, Types.PROC, Types.UNIT);
56 // Add logging methods
57 for(String methodName : LOGGING_METHODS) {
58 { // isEnabled :: <Proc> Boolean
59 String completeMethodName = generateIsEnabledName(methodName);
60 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", completeMethodName, Types.PROC, Types.BOOLEAN, Logger);
61 SCLValue value = new SCLValue(Name.create(getName(), completeMethodName));
62 value.setType(isEnabledType);
63 value.setMacroRule(new MacroRule() {
65 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
66 ConcreteModule module = context.getCompilationContext().module;
69 identifier = module.getName().replaceAll("/", ".");
71 identifier = CommandSession.class.getName();
72 apply.set(new ELiteral(javaMethod), new Expression[] {
73 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger)
80 { // logging function with single String-parameter :: String -> <Proc> ()
81 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
82 SCLValue value = new SCLValue(Name.create(getName(), methodName));
83 value.setType(loggingType);
84 value.setMacroRule(new MacroRule() {
86 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
87 ConcreteModule module = context.getCompilationContext().module;
90 identifier = module.getName().replaceAll("/", ".");
92 identifier = CommandSession.class.getName();
93 apply.set(new ELiteral(javaMethod), new Expression[] {
94 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
102 { // logging function with two parameters :: String -> Throwable -> <Proc> ()
103 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING, Throwable);
104 SCLValue value = new SCLValue(Name.create(getName(), methodName + "E"));
105 value.setType(loggingTypeWithException);
106 value.setMacroRule(new MacroRule() {
108 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
109 ConcreteModule module = context.getCompilationContext().module;
112 identifier = module.getName().replaceAll("/", ".");
114 identifier = CommandSession.class.getName();
115 apply.set(new ELiteral(javaMethod), new Expression[] {
116 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
125 { // logging function with two parameters :: Marker -> String -> <Proc> ()
126 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING);
127 SCLValue value = new SCLValue(Name.create(getName(), methodName + "M"));
128 value.setType(loggingTypeWithMarker);
129 value.setMacroRule(new MacroRule() {
131 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
132 ConcreteModule module = context.getCompilationContext().module;
135 identifier = module.getName().replaceAll("/", ".");
137 identifier = CommandSession.class.getName();
138 apply.set(new ELiteral(javaMethod), new Expression[] {
139 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
148 { // logging function with three parameters :: Marker -> String -> Throwable -> <Proc> ()
149 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING, Throwable);
150 SCLValue value = new SCLValue(Name.create(getName(), methodName + "ME"));
151 value.setType(loggingTypeWithMarkerAndException);
152 value.setMacroRule(new MacroRule() {
154 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
155 ConcreteModule module = context.getCompilationContext().module;
158 identifier = module.getName().replaceAll("/", ".");
160 identifier = CommandSession.class.getName();
161 apply.set(new ELiteral(javaMethod), new Expression[] {
162 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
174 setParentClassLoader(LoggerFactory.class.getClassLoader());
177 private static String generateIsEnabledName(String level) {
178 return "is" + capitalizeFirstCharacter(level) + "Enabled";
181 private static String capitalizeFirstCharacter(String input) {
182 return input.substring(0, 1).toUpperCase() + input.substring(1);